Skip to content

Instantly share code, notes, and snippets.

@snorfalorpagus
Created December 18, 2017 14:22
Show Gist options
  • Save snorfalorpagus/445223684430ea11c4939c187febeb66 to your computer and use it in GitHub Desktop.
Save snorfalorpagus/445223684430ea11c4939c187febeb66 to your computer and use it in GitHub Desktop.
katana in qgis 2
"""
Split large polygons into smaller parts for faster intersections
https://snorfalorpagus.net/blog/2016/03/13/splitting-large-polygons-for-faster-intersections/
"""
##Input=vector
##Threshold=number 500.0
##Recursion=number 250
##Output=output vector
import processing
from qgis.core import QgsMessageLog
from qgis.core import QGis
from qgis.core import QgsGeometry, QgsPoint, QgsRectangle
from processing.tools.vector import VectorWriter
threshold = Threshold
layer_input = processing.getObject(Input)
data_provider = layer_input.dataProvider()
fields = data_provider.fields()
crs = data_provider.crs()
writer = VectorWriter(
destination=Output,
encoding=None,
fields=fields,
geometryType=QGis.WKBMultiPolygon,
crs=crs
)
def katana(geom, threshold, count):
bbox = geom.boundingBox()
width = bbox.width()
height = bbox.height()
xmin = bbox.xMinimum()
ymin = bbox.yMinimum()
xmax = bbox.xMaximum()
ymax = bbox.yMaximum()
xcenter = xmin + width / 2.0
ycenter = ymin + height / 2.0
if max(width, height) <= threshold or count == Recursion:
return [geom]
if height >= width:
# split left to right
a = QgsGeometry.fromRect(QgsRectangle(xmin, ymin, xmax, ycenter))
b = QgsGeometry.fromRect(QgsRectangle(xmin, ycenter, xmax, ymax))
else:
# split top to bottom
a = QgsGeometry.fromRect(QgsRectangle(xmin, ymin, xcenter, ymax))
b = QgsGeometry.fromRect(QgsRectangle(xcenter, ymin, xmax, ymax))
result = []
for d in (a, b,):
c = geom.intersection(d)
if c.isMultipart():
for g in c.asGeometryCollection():
result.extend(katana(g, threshold, count + 1))
else:
result.extend(katana(c, threshold, count + 1))
return result
progress.setPercentage(0)
num_features = layer_input.featureCount()
for n, feature in enumerate(processing.features(layer_input)):
geoms = katana(feature.geometry(), threshold, 0)
for geom in geoms:
feature.setGeometry(geom)
writer.addFeature(feature)
progress.setPercentage(int(100*(n+1)/float(num_features)))
progress.setPercentage(100)
del(katana)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment