This will convert your polygons into arcs very quickly. You need 2 layers in table of content: 1st - polylines, 2nd - polygons
import arcpy, traceback, os, sys,time
from arcpy import env
env.overwriteOutput = True
dissolved="in_memory/dissolved"
try:
def showPyMessage():
arcpy.AddMessage(str(time.ctime()) + " - " + message)
mxd = arcpy.mapping.MapDocument("CURRENT")
theLinksLayer=arcpy.mapping.ListLayers(mxd)[0]
PGONS=arcpy.mapping.ListLayers(mxd)[1]
arcpy.DeleteFeatures_management(theLinksLayer)
curT = arcpy.da.InsertCursor(theLinksLayer,"SHAPE@")
with arcpy.da.SearchCursor(PGONS, "Shape@") as cursor:
for row in cursor:
feat = row[0].boundary()
curT.insertRow((feat,))
arcpy.Dissolve_management(theLinksLayer, dissolved,"","", "SINGLE_PART")
arcpy.DeleteFeatures_management(theLinksLayer)
m=0
arcpy.AddMessage("Dissolving ...")
curT = arcpy.da.InsertCursor(theLinksLayer,"SHAPE@")
with arcpy.da.SearchCursor(dissolved, "SHAPE@") as cursor:
for row in cursor:
m+=1
curT.insertRow((row[0],))
arcpy.Delete_management("in_memory")
arcpy.RefreshActiveView()
arcpy.AddMessage("\nPolygons unbuilt into %i lines\n" %m)
del curT
except:
message = "\n*** PYTHON ERRORS *** "; showPyMessage()
message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
message = "Python Error Info: " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()
From here it is enough to spatially join lines to polygons (one to many, SHARE_A_LINE_SEGMENT_WITH) and dissolve output using line name and first, last polygon IDs to get this:
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.
Best Answer
Let's assume there are two layers 'borders' (line) and 'ocean' (polygon), see image below.
With the "Difference" geoalgorithm can be found under
Vector > Geoprocessing Tools > Difference
, it is possible to delete edges of the polygons that border the ocean.The output new 'borders' layer will look as following
Keep on mind that this object is a
MULTILINESTRING
.In case, these features should be treated as a simple
LINESTRING
, please proceed with "Multipart to singleparts" can be found underVector > Geometry Tools > Multipart to singleparts
.There is a useful subject on this topic, see Convert MultiLineString to LineString using QGIS