mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
review and cleanup Convex Hull tool, also move some common routines to
utils module and update other algs accordingly
This commit is contained in:
parent
11d567c771
commit
48e9f42891
@ -23,139 +23,38 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
from sextante.core.GeoAlgorithm import GeoAlgorithm
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
|
||||
from qgis.core import *
|
||||
from sextante.parameters.ParameterVector import ParameterVector
|
||||
|
||||
from sextante.core.GeoAlgorithm import GeoAlgorithm
|
||||
from sextante.core.QGisLayers import QGisLayers
|
||||
from sextante.outputs.OutputVector import OutputVector
|
||||
from sextante.algs.ftools import FToolsUtils as utils
|
||||
from sextante.core.SextanteLog import SextanteLog
|
||||
|
||||
from sextante.parameters.ParameterVector import ParameterVector
|
||||
from sextante.parameters.ParameterTableField import ParameterTableField
|
||||
from sextante.parameters.ParameterSelection import ParameterSelection
|
||||
|
||||
from sextante.outputs.OutputVector import OutputVector
|
||||
|
||||
from sextante.algs.ftools import FToolsUtils as utils
|
||||
|
||||
class ConvexHull(GeoAlgorithm):
|
||||
|
||||
INPUT = "INPUT"
|
||||
OUTPUT = "OUTPUT"
|
||||
FIELD = "FIELD"
|
||||
METHOD = "METHOD"
|
||||
METHODS = ["Create single minimum convex hull", "Create convex hulls based on field"]
|
||||
METHODS = ["Create single minimum convex hull",
|
||||
"Create convex hulls based on field"
|
||||
]
|
||||
|
||||
#===========================================================================
|
||||
# def getIcon(self):
|
||||
# return QtGui.QIcon(os.path.dirname(__file__) + "/icons/convex_hull.png")
|
||||
#===========================================================================
|
||||
|
||||
def processAlgorithm(self, progress):
|
||||
useField = (self.getParameterValue(ConvexHull.METHOD) == 1)
|
||||
field = self.getParameterValue(ConvexHull.FIELD)
|
||||
vlayerA = QGisLayers.getObjectFromUri(self.getParameterValue(ConvexHull.INPUT))
|
||||
GEOS_EXCEPT = True
|
||||
FEATURE_EXCEPT = True
|
||||
vproviderA = vlayerA.dataProvider()
|
||||
#allAttrsA = vproviderA.attributeIndexes()
|
||||
#vproviderA.select(allAttrsA)
|
||||
fields = [QgsField("ID", QVariant.Int),
|
||||
QgsField("Area", QVariant.Double),
|
||||
QgsField("Perim", QVariant.Double)]
|
||||
writer = self.getOutputFromName(ConvexHull.OUTPUT).getVectorWriter(fields, QGis.WKBPolygon, vproviderA.crs())
|
||||
inFeat = QgsFeature()
|
||||
outFeat = QgsFeature()
|
||||
inGeom = QgsGeometry()
|
||||
outGeom = QgsGeometry()
|
||||
nElement = 0
|
||||
index = vproviderA.fieldNameIndex(field)
|
||||
|
||||
features = QGisLayers.features(vlayerA)
|
||||
nFeat = len(features)
|
||||
|
||||
if useField:
|
||||
unique = utils.getUniqueValues(vproviderA, index)
|
||||
nFeat = nFeat * len(unique)
|
||||
for i in unique:
|
||||
hull = []
|
||||
first = True
|
||||
outID = 0
|
||||
#vproviderA.select(allAttrsA)
|
||||
features = QGisLayers.features(vlayerA)
|
||||
for inFeat in features:
|
||||
atMap = inFeat.attributes()
|
||||
idVar = atMap[ index ]
|
||||
if idVar.toString().trimmed() == i.toString().trimmed():
|
||||
if first:
|
||||
outID = idVar
|
||||
first = False
|
||||
inGeom = QgsGeometry(inFeat.geometry())
|
||||
points = utils.extractPoints(inGeom)
|
||||
hull.extend(points)
|
||||
nElement += 1
|
||||
progress.setPercentage(int(nElement / nFeat * 100))
|
||||
if len(hull) >= 3:
|
||||
tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
|
||||
try:
|
||||
outGeom = tmpGeom.convexHull()
|
||||
outFeat.setGeometry(outGeom)
|
||||
(area, perim) = self.simpleMeasure(outGeom)
|
||||
outFeat.addAttribute(0, QVariant(outID))
|
||||
outFeat.addAttribute(1, QVariant(area))
|
||||
outFeat.addAttribute(2, QVariant(perim))
|
||||
writer.addFeature(outFeat)
|
||||
except:
|
||||
GEOS_EXCEPT = False
|
||||
continue
|
||||
else:
|
||||
hull = []
|
||||
#vproviderA.select(allAttrsA)
|
||||
features = QGisLayers.features(vlayerA)
|
||||
for inFeat in features:
|
||||
inGeom = QgsGeometry(inFeat.geometry())
|
||||
points = utils.extractPoints(inGeom)
|
||||
hull.extend(points)
|
||||
nElement += 1
|
||||
progress.setPercentage(int(nElement / nFeat * 100))
|
||||
tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
|
||||
try:
|
||||
outGeom = tmpGeom.convexHull()
|
||||
outFeat.setGeometry(outGeom)
|
||||
(area, perim) = self.simpleMeasure(outGeom)
|
||||
#outFeat.addAttribute(0, QVariant("1"))
|
||||
#outFeat.addAttribute(1, QVariant(area))
|
||||
#outFeat.addAttribute(2, QVariant(perim))
|
||||
writer.addFeature(outFeat)
|
||||
except:
|
||||
GEOS_EXCEPT = False
|
||||
|
||||
del writer
|
||||
|
||||
if not GEOS_EXCEPT:
|
||||
SextanteLog.addToLog(SextanteLog.LOG_WARNING, "Geometry exception while computing convex hull")
|
||||
if not FEATURE_EXCEPT:
|
||||
SextanteLog.addToLog(SextanteLog.LOG_WARNING, "Feature exception while computing convex hull")
|
||||
|
||||
def simpleMeasure(self, inGeom):
|
||||
measure = QgsDistanceArea()
|
||||
attr1 = measure.measure(inGeom)
|
||||
if inGeom.type() == QGis.Polygon:
|
||||
attr2 = self.perimMeasure(inGeom, measure)
|
||||
else:
|
||||
attr2 = attr1
|
||||
return (attr1, attr2)
|
||||
|
||||
def perimMeasure(self, inGeom, measure):
|
||||
value = 0.00
|
||||
if inGeom.isMultipart():
|
||||
poly = inGeom.asMultiPolygon()
|
||||
for k in poly:
|
||||
for j in k:
|
||||
value = value + measure.measureLine(j)
|
||||
else:
|
||||
poly = inGeom.asPolygon()
|
||||
for k in poly:
|
||||
value = value + measure.measureLine(k)
|
||||
return value
|
||||
|
||||
def defineCharacteristics(self):
|
||||
self.name = "Convex hull"
|
||||
self.group = "Vector geometry tools"
|
||||
@ -163,4 +62,120 @@ class ConvexHull(GeoAlgorithm):
|
||||
self.addParameter(ParameterTableField(ConvexHull.FIELD, "Field", ConvexHull.INPUT))
|
||||
self.addParameter(ParameterSelection(ConvexHull.METHOD, "Method", ConvexHull.METHODS))
|
||||
self.addOutput(OutputVector(ConvexHull.OUTPUT, "Convex hull"))
|
||||
#=========================================================
|
||||
|
||||
def processAlgorithm(self, progress):
|
||||
useField = (self.getParameterValue(ConvexHull.METHOD) == 1)
|
||||
fieldName = self.getParameterValue(ConvexHull.FIELD)
|
||||
layer = QGisLayers.getObjectFromUri(self.getParameterValue(ConvexHull.INPUT))
|
||||
|
||||
GEOS_EXCEPT = True
|
||||
FEATURE_EXCEPT = True
|
||||
|
||||
index = layer.fieldNameIndex(fieldName)
|
||||
fType = layer.pendingFields()[index].type()
|
||||
f = QgsField("value")
|
||||
f.setType(QVariant.String)
|
||||
f.setLength(255)
|
||||
if useField:
|
||||
if fType == QVariant.Int:
|
||||
f.setType(QVariant.Int)
|
||||
f.setLength(20)
|
||||
elif fType == QVariant.Double:
|
||||
f.setType(QVariant.Double)
|
||||
f.setLength(20)
|
||||
f.setPrecision(6)
|
||||
else:
|
||||
f.setType(QVariant.String)
|
||||
f.setLength(255)
|
||||
|
||||
fields = [QgsField("id", QVariant.Int, "", 20),
|
||||
f,
|
||||
QgsField("area", QVariant.Double, "", 20, 6),
|
||||
QgsField("perim", QVariant.Double, "", 20, 6)
|
||||
]
|
||||
|
||||
writer = self.getOutputFromName(ConvexHull.OUTPUT).getVectorWriter(fields, QGis.WKBPolygon, layer.dataProvider().crs())
|
||||
|
||||
outFeat = QgsFeature()
|
||||
inGeom = QgsGeometry()
|
||||
outGeom = QgsGeometry()
|
||||
|
||||
current = 0
|
||||
|
||||
fid = 0
|
||||
val = ""
|
||||
if useField:
|
||||
unique = layer.uniqueValues(index)
|
||||
total = 100.0 / float(layer.featureCount() * len (unique))
|
||||
|
||||
for i in unique:
|
||||
hull = []
|
||||
first = True
|
||||
features = QGisLayers.features(layer)
|
||||
for f in features:
|
||||
idVar = f.attribute(fieldName)
|
||||
if idVar.toString().trimmed() == i.toString().trimmed():
|
||||
if first:
|
||||
val = idVar
|
||||
first = False
|
||||
inGeom = QgsGeometry(f.geometry())
|
||||
points = utils.extractPoints(inGeom)
|
||||
hull.extend(points)
|
||||
current += 1
|
||||
progress.setPercentage(int(current * total))
|
||||
|
||||
if len(hull) >= 3:
|
||||
tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
|
||||
try:
|
||||
outGeom = tmpGeom.convexHull()
|
||||
(area, perim) = utils.simpleMeasure(outGeom)
|
||||
outFeat.setGeometry(outGeom)
|
||||
outFeat.setAttributes([QVariant(fid),
|
||||
QVariant(val),
|
||||
QVariant(area),
|
||||
QVariant(perim)
|
||||
])
|
||||
#~ outFeat.setAttribute("id", QVariant(fid))
|
||||
#~ outFeat.setAttribute("value", QVariant(val))
|
||||
#~ outFeat.setAttribute("area", QVariant(area))
|
||||
#~ outFeat.setAttribute("perim", QVariant(perim))
|
||||
writer.addFeature(outFeat)
|
||||
except:
|
||||
GEOS_EXCEPT = False
|
||||
continue
|
||||
fid += 1
|
||||
else:
|
||||
hull = []
|
||||
total = 100.0 / float(layer.featureCount())
|
||||
features = QGisLayers.features(layer)
|
||||
for f in features:
|
||||
inGeom = QgsGeometry(f.geometry())
|
||||
points = utils.extractPoints(inGeom)
|
||||
hull.extend(points)
|
||||
current += 1
|
||||
progress.setPercentage(int(current * total))
|
||||
|
||||
tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
|
||||
try:
|
||||
outGeom = tmpGeom.convexHull()
|
||||
(area, perim) = utils.simpleMeasure(outGeom)
|
||||
outFeat.setGeometry(outGeom)
|
||||
outFeat.setAttributes([QVariant(0),
|
||||
QVariant("all"),
|
||||
QVariant(area),
|
||||
QVariant(perim)
|
||||
])
|
||||
#print outFeat.setAttribute("id", QVariant(0))
|
||||
#print outFeat.setAttribute("value", QVariant("all"))
|
||||
#print outFeat.setAttribute("area", QVariant(area))
|
||||
#print outFeat.setAttribute("perim", QVariant(perim))
|
||||
writer.addFeature(outFeat)
|
||||
except:
|
||||
GEOS_EXCEPT = False
|
||||
|
||||
del writer
|
||||
|
||||
if not GEOS_EXCEPT:
|
||||
SextanteLog.addToLog(SextanteLog.LOG_WARNING, "Geometry exception while computing convex hull")
|
||||
if not FEATURE_EXCEPT:
|
||||
SextanteLog.addToLog(SextanteLog.LOG_WARNING, "Feature exception while computing convex hull")
|
||||
|
@ -24,13 +24,19 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
from PyQt4.QtCore import *
|
||||
|
||||
from qgis.core import *
|
||||
|
||||
from sextante.core.GeoAlgorithm import GeoAlgorithm
|
||||
from sextante.core.QGisLayers import QGisLayers
|
||||
|
||||
from sextante.parameters.ParameterVector import ParameterVector
|
||||
from sextante.parameters.ParameterSelection import ParameterSelection
|
||||
|
||||
from sextante.outputs.OutputVector import OutputVector
|
||||
|
||||
from sextante.algs.ftools import FToolsUtils as utils
|
||||
|
||||
class ExportGeometryInfo(GeoAlgorithm):
|
||||
|
||||
INPUT = "INPUT"
|
||||
@ -56,7 +62,6 @@ class ExportGeometryInfo(GeoAlgorithm):
|
||||
|
||||
self.addOutput(OutputVector(self.OUTPUT, "Output layer"))
|
||||
|
||||
|
||||
def processAlgorithm(self, progress):
|
||||
layer = QGisLayers.getObjectFromUri(self.getParameterValue(self.INPUT))
|
||||
method = self.getParameterValue(self.METHOD)
|
||||
@ -90,7 +95,7 @@ class ExportGeometryInfo(GeoAlgorithm):
|
||||
# 2 - ellipsoidal
|
||||
if method == 2:
|
||||
settings = QSettings()
|
||||
ellips = settings.value("/qgis/measure/ellipsoid", "WGS84").toString()
|
||||
ellips = QgsProject.instance().readEntry("Measure", "/Ellipsoid", GEO_NONE)[0]
|
||||
crs = layer.crs().srsid()
|
||||
elif method == 1:
|
||||
mapCRS = QGisLayers.iface.mapCanvas().mapRenderer().destinationCrs()
|
||||
@ -109,7 +114,7 @@ class ExportGeometryInfo(GeoAlgorithm):
|
||||
if method == 1:
|
||||
inGeom.transform(coordTransform)
|
||||
|
||||
(attr1, attr2) = self.simpleMeasure(inGeom, method, ellips, crs)
|
||||
(attr1, attr2) = utils.simpleMeasure(inGeom, method, ellips, crs)
|
||||
|
||||
outFeat.setGeometry(inGeom)
|
||||
atMap = inFeat.attributes()
|
||||
@ -123,42 +128,3 @@ class ExportGeometryInfo(GeoAlgorithm):
|
||||
progress.setPercentage(int(current * total))
|
||||
|
||||
del writer
|
||||
|
||||
def simpleMeasure(self, geom, method, ellips, crs):
|
||||
if geom.wkbType() in [QGis.WKBPoint, QGis.WKBPoint25D]:
|
||||
pt = geom.asPoint()
|
||||
attr1 = pt.x()
|
||||
attr2 = pt.y()
|
||||
elif geom.wkbType() in [QGis.WKBMultiPoint, QGis.WKBMultiPoint25D]:
|
||||
pt = inGeom.asMultiPoint()
|
||||
attr1 = pt[0].x()
|
||||
attr2 = pt[0].y()
|
||||
else:
|
||||
measure = QgsDistanceArea()
|
||||
|
||||
if method == 2:
|
||||
measure.setSourceCrs(crs)
|
||||
measure.setEllipsoid(ellips)
|
||||
measure.setEllipsoidalMode(True)
|
||||
|
||||
attr1 = measure.measure(geom)
|
||||
if geom.type() == QGis.Polygon:
|
||||
attr2 = self.perimMeasure(geom, measure)
|
||||
else:
|
||||
attr2 = None
|
||||
|
||||
return (attr1, attr2)
|
||||
|
||||
def perimMeasure(self, geom, measure):
|
||||
value = 0.0
|
||||
if geom.isMultipart():
|
||||
polygons = geom.asMultiPolygon()
|
||||
for p in polygons:
|
||||
for line in p:
|
||||
value += measure.measureLine(line)
|
||||
else:
|
||||
poly = geom.asPolygon()
|
||||
for r in poly:
|
||||
value += measure.measureLine(r)
|
||||
|
||||
return value
|
||||
|
@ -96,6 +96,35 @@ def extractPoints( geom ):
|
||||
|
||||
return points
|
||||
|
||||
def simpleMeasure(geom, method=0, ellips=None, crs=None):
|
||||
# method defines calculation type:
|
||||
# 0 - layer CRS
|
||||
# 1 - project CRS
|
||||
# 2 - ellipsoidal
|
||||
if geom.wkbType() in [QGis.WKBPoint, QGis.WKBPoint25D]:
|
||||
pt = geom.asPoint()
|
||||
attr1 = pt.x()
|
||||
attr2 = pt.y()
|
||||
elif geom.wkbType() in [QGis.WKBMultiPoint, QGis.WKBMultiPoint25D]:
|
||||
pt = inGeom.asMultiPoint()
|
||||
attr1 = pt[0].x()
|
||||
attr2 = pt[0].y()
|
||||
else:
|
||||
measure = QgsDistanceArea()
|
||||
|
||||
if method == 2:
|
||||
measure.setSourceCrs(crs)
|
||||
measure.setEllipsoid(ellips)
|
||||
measure.setEllipsoidalMode(True)
|
||||
|
||||
attr1 = measure.measure(geom)
|
||||
if geom.type() == QGis.Polygon:
|
||||
attr2 = measure.measurePerimeter(geom)
|
||||
else:
|
||||
attr2 = attr1
|
||||
|
||||
return (attr1, attr2)
|
||||
|
||||
def getUniqueValues(layer, fieldIndex):
|
||||
values = []
|
||||
layer.select([fieldIndex], QgsRectangle(), False)
|
||||
|
Loading…
x
Reference in New Issue
Block a user