Skip to content

Instantly share code, notes, and snippets.

@bbecquet
Last active July 22, 2021 07:38
Show Gist options
  • Save bbecquet/b20112737290a263286e6aa203a69026 to your computer and use it in GitHub Desktop.
Save bbecquet/b20112737290a263286e6aa203a69026 to your computer and use it in GitHub Desktop.
Waterlining function for QGIS
from qgis.core import *
@qgsfunction(args='auto', group='Custom')
def waterlines(inc, start, nb_max, grow_ratio, feature, parent):
"""
Creates repeated buffered polygons
for a waterlining effect like on old engraved maps.
<h2>Arguments</h2>
<table>
<tr>
<td>inc</dt>
<td>Distance increment between each line, in current "units". Negative for inner lines, positive for outer.</td>
</tr>
<tr>
<td>start</dt>
<td>Distance where to draw the first line.</td>
</tr>
<tr>
<td>nb_max</dt>
<td>Max number of lines. If -1, fills the entire space.</td>
</tr>
<tr>
<td>grow_ratio</dt>
<td>Multiplication factor applied at each step. 1 to get equally spaced lines, >1 for increasing distance each time.</td>
</tr>
</table>
<h2>Example usage:</h2>
<ul>
<li>waterlines(-50, 0, -1, 1) -> equally spaced lines, spaced by 50, filling the entire polygon.</li>
<li>waterlines(50, 0, 10, 1.25) -> 10 lines, growing from the polygon, spaced by 50 in the first iteration, then growing by a 1.25 factor.</li>
</ul>
"""
geom = feature.geometry()
if geom.type() != QgsWkbTypes.PolygonGeometry:
return NULL
dist = start
lines = []
nb_loops = 500 if nb_max < 0 else nb_max # use 500 as default max to prevent infinite loops
while nb_loops > 0:
line = geom.buffer(dist, 8)
if line.isNull() or line.isEmpty() or not line.isGeosValid():
break
lines.append(line)
dist = (dist + inc) * grow_ratio
nb_loops -= 1
return QgsGeometry.collectGeometry(lines)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment