2

I have a file containing polygons that delineate the boundaries of municipalities within a specific region. I want to convert the polygon boundaries to lines. The resulting lines should be split depending on the line/boundary being shared with the neighbouring polygon. So each part of a line that is shared with a specific neighbour should be a separate LineString.

(Each polygon is accompanied by a unique "wikidata" field corresponding to each municipality.)

The image below shows the before state (3 polygons/closed MultiLineStrings) and the second image shows the desired state (3 closed MultiLineStrings, but consisting of 6 LineStrings). Each colour represents a different LineString. Shared nodes between two or more LineStrings are shown with grey dots.

enter image description here

10
  • 6
    Topologically, the polygon rings within multipolygons are forbidden from sharing borders. Please Edit the Question so that folks don't need to follow a link to understand the relationships involved.
    – Vince
    Commented Apr 2 at 20:27
  • 2
    Yes they are. Tons of examples and explanations out there. Here's Microsoft's example. If the rings of a multipolygon overlap (touch at more than a point), it is not valid. They can't share area, either.
    – Vince
    Commented Apr 2 at 21:47
  • 2
    Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.
    – Community Bot
    Commented Apr 2 at 23:04
  • 1
    I suggest you Edit the Question to include a sketch as an image (JPEG/PNG). Include before and and after frames.
    – Vince
    Commented Apr 3 at 11:06
  • 2
    Added a sketch.
    – Dimitar
    Commented Apr 3 at 16:15

2 Answers 2

2

It took some time but I found the solution. In case anyone needs it:

  1. "Check validity" tool
  2. "Boundary" tool
  3. "v.clean" from GRASS Vector tools with only bpol tool
1

You can create this effect using Geomtry Genrator with this expression to create a separate line for each shared path between two polygons (to create actual lines with Geometry by Expression, see below):

collect_geometries(
    with_variable( 'my_id', @id,
    array_foreach(
        eval ('overlay_intersects (@layer, @id, filter:=@id<' || @my_id || ')'),
        line_merge( 
            intersection(
                boundary(geometry(get_feature_by_id(@layer, @element))),
                boundary($geometry)
            )
        )
    ))
)

enter image description here

To visually represent all in different colors, I used data driver override for the color -> Assistant... -> and inserted the following expression in Source:

@geometry_part_num ||   
array_find (array_sort (array_agg($id)), $id)+1

Select a color ramp, tweak values from/to and and maybe apply a transformation curve to really get clearly discernable, distinct color values as in the screenshot above.


To create actual lines with Geometry by Expression, use this expression (replace Layername with the name of the polygon layer), then run Multipart to single parts to get a separate feature for each part of the border:

collect_geometries(
with_variable( 'my_id', @id,
    array_filter (
        array_foreach(
            eval ('overlay_intersects (''Layername'', @id, filter:=@id<' || @my_id || ')'),
            line_merge( 
                intersection(
                    boundary (geometry (get_feature_by_id ('Layername', @element))),
                    boundary($geometry)
                )
            )
        ),
        @element is not NULL
    )
))

Now, to get different colors for neighboring lines, proceed as follows:

  1. Create a (very tiny) buffer around the lines.
  2. Use Topological coloring for the buffer.
  3. Use Join attributes by location (lines form step 1 -> are within -> buffer from step 2) and selct the field color_id.
  4. Then use Categorized layer style based on the attribute created in step 3 and you're done.

Based on topological coloring with only 4 colors to get clearly distinguishabel colors: enter image description here

Not the answer you're looking for? Browse other questions tagged or ask your own question.