Skip to content

Commit e527fe3

Browse files
committedSep 21, 2013
Added "eliminate sliver polygons" algorithm skeleton(still a draft first version)
1 parent 8a48b9f commit e527fe3

File tree

2 files changed

+187
-1
lines changed

2 files changed

+187
-1
lines changed
 

‎python/plugins/processing/algs/QGISAlgorithmProvider.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
***************************************************************************
1818
"""
1919
from processing.algs.Polygonize import Polygonize
20+
from processing.algs.ftools.Eliminate import Eliminate
2021

2122
__author__ = 'Victor Olaya'
2223
__date__ = 'December 2012'
@@ -112,7 +113,7 @@ def __init__(self):
112113
ExportGeometryInfo(), Centroids(), Delaunay(), VoronoiPolygons(),
113114
SimplifyGeometries(), DensifyGeometries(), DensifyGeometriesInterval(),
114115
MultipartToSingleparts(), SinglePartsToMultiparts(), PolygonsToLines(),
115-
LinesToPolygons(), ExtractNodes(),
116+
LinesToPolygons(), ExtractNodes(),Eliminate(),
116117
# geoprocessing
117118
ConvexHull(), FixedDistanceBuffer(), VariableDistanceBuffer(),
118119
Dissolve(), Difference(), Intersection(), Union(), Clip(),
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
Eliminate.py
6+
---------------------
7+
Date : August 2012
8+
Copyright : (C) 2013 by Bernhard Str�bl
9+
Email : bernhard.stroebl@jena.de
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
from processing.parameters.ParameterSelection import ParameterSelection
20+
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
21+
from PyQt4 import QtCore
22+
23+
__author__ = 'Bernhard Strobl'
24+
__date__ = 'August 2013'
25+
__copyright__ = '(C) 2013, Bernhard Strobl'
26+
# This will get replaced with a git SHA1 when you do a git archive
27+
__revision__ = '$Format:%H$'
28+
29+
from PyQt4.QtCore import *
30+
from qgis.core import *
31+
from processing.core.GeoAlgorithm import GeoAlgorithm
32+
from processing.tools import dataobjects
33+
from processing.parameters.ParameterVector import ParameterVector
34+
from processing.outputs.OutputVector import OutputVector
35+
36+
37+
class Eliminate(GeoAlgorithm):
38+
39+
INPUT = "INPUT"
40+
OUTPUT = "OUTPUT"
41+
MODE = "MODE"
42+
43+
MODES = ["Area", "Common boundary"]
44+
MODE_AREA = 0
45+
MODE_BOUNDARY = 1
46+
47+
48+
def defineCharacteristics(self):
49+
self.name = "Eliminate sliver polygons"
50+
self.group = "Vector geometry tools"
51+
self.addParameter(ParameterVector(self.INPUT, "Input layer", [ParameterVector.VECTOR_TYPE_POLYGON]))
52+
self.addParameter(ParameterSelection(self.MODE, "Segments", self.MODES))
53+
self.addOutput(OutputVector(self.OUTPUT, "Cleaned layer"))
54+
55+
def processAlgorithm(self, progress):
56+
inLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
57+
boundary = self.getParameterValue(self.MODE) == self.MODE_BOUNDARY
58+
59+
# keep references to the features to eliminate
60+
fidsToEliminate = inLayer.selectedFeaturesIds()
61+
62+
63+
provider = inLayer.dataProvider()
64+
output = self.getOutputFromName(self.OUTPUT)
65+
writer = output.getVectorWriter( provider.fields(),
66+
provider.geometryType(),
67+
inLayer.crs() )
68+
69+
#write all features to output layer
70+
iterator = inLayer.getFeatures()
71+
for feature in iterator:
72+
writer.addFeature(feature)
73+
74+
#Open the layer to start cleaning it
75+
outFileName = output.value
76+
outLayer = QgsVectorLayer(outFileName, QtCore.QFileInfo(outFileName).completeBaseName(), "ogr")
77+
78+
79+
# delete features to be eliminated in outLayer
80+
outLayer.setSelectedFeatures(fidsToEliminate)
81+
outLayer.startEditing()
82+
83+
if outLayer.deleteSelectedFeatures():
84+
if self.saveChanges(outLayer):
85+
outLayer.startEditing()
86+
else:
87+
raise GeoAlgorithmExecutionException("Could not delete features")
88+
89+
# ANALYZE
90+
start = 20.00
91+
progress.setPercentage(start)
92+
add = 80.00 / len(fidsToEliminate)
93+
94+
lastLen = 0
95+
geomsToMerge = dict()
96+
97+
# we go through the list and see if we find any polygons we can merge the selected with
98+
# if we have no success with some we merge and then restart the whole story
99+
while (lastLen != inLayer.selectedFeatureCount()): #check if we made any progress
100+
lastLen = inLayer.selectedFeatureCount()
101+
fidsToDeselect = []
102+
103+
#iterate over the polygons to eliminate
104+
for fid2Eliminate in inLayer.selectedFeaturesIds():
105+
feat = QgsFeature()
106+
107+
if inLayer.getFeatures( QgsFeatureRequest().setFilterFid( fid2Eliminate ).setSubsetOfAttributes([]) ).nextFeature( feat ):
108+
geom2Eliminate = feat.geometry()
109+
bbox = geom2Eliminate.boundingBox()
110+
fit = outLayer.getFeatures( QgsFeatureRequest().setFilterRect( bbox ) )
111+
mergeWithFid = None
112+
mergeWithGeom = None
113+
max = 0
114+
115+
selFeat = QgsFeature()
116+
while fit.nextFeature(selFeat):
117+
selGeom = selFeat.geometry()
118+
119+
if geom2Eliminate.intersects(selGeom): # we have a candidate
120+
iGeom = geom2Eliminate.intersection(selGeom)
121+
122+
if boundary:
123+
selValue = iGeom.length()
124+
else:
125+
# we need a common boundary
126+
if 0 < iGeom.length():
127+
selValue = selGeom.area()
128+
else:
129+
selValue = 0
130+
131+
if selValue > max:
132+
max = selValue
133+
mergeWithFid = selFeat.id()
134+
mergeWithGeom = QgsGeometry(selGeom) # deep copy of the geometry
135+
136+
if mergeWithFid != None: # a successful candidate
137+
newGeom = mergeWithGeom.combine(geom2Eliminate)
138+
139+
if outLayer.changeGeometry(mergeWithFid, newGeom):
140+
# write change back to disc
141+
if self.saveChanges(outLayer):
142+
outLayer.startEditing()
143+
else:
144+
return
145+
146+
# mark feature as eliminated in inLayer
147+
fidsToDeselect.append(fid2Eliminate)
148+
else:
149+
raise GeoAlgorithmExecutionException("Could not replace geometry of feature with id %s" % (mergeWithFid))
150+
151+
start = start + add
152+
progress.setPercentage(start)
153+
# end for fid2Eliminate
154+
155+
# deselect features that are already eliminated in inLayer
156+
inLayer.deselect(fidsToDeselect)
157+
158+
#end while
159+
160+
if inLayer.selectedFeatureCount() > 0:
161+
# copy all features that could not be eliminated to outLayer
162+
if outLayer.addFeatures(inLayer.selectedFeatures()):
163+
# inform user
164+
fidList = ""
165+
166+
for fid in inLayer.selectedFeaturesIds():
167+
if not fidList == "":
168+
fidList += ", "
169+
170+
fidList += str(fid)
171+
172+
raise GeoAlgorithmExecutionException("Could not eliminate features with these ids:\n%s" % (fidList))
173+
else:
174+
raise GeoAlgorithmExecutionException("Could not add features")
175+
176+
# stop editing outLayer and commit any pending changes
177+
self.saveChanges(outLayer)
178+
179+
def saveChanges(self, outLayer):
180+
if not outLayer.commitChanges():
181+
msg = ""
182+
for aStrm in outLayer.commitErrors():
183+
msg = msg + "\n" + aStrm
184+
outLayer.rollBack()
185+
raise GeoAlgorithmExecutionException("Commit error:\n%s" % (msg))

0 commit comments

Comments
 (0)
Please sign in to comment.