From a6418d6502ddb13330cbec37a4a5ce47741cf229 Mon Sep 17 00:00:00 2001 From: Alexander Bruy Date: Mon, 1 Oct 2012 20:48:06 +0300 Subject: [PATCH] review Export geometry info tool, sync with master --- .../sextante/ftools/ExportGeometryInfo.py | 248 ++++++++++-------- python/plugins/sextante/ftools/FToolsUtils.py | 6 +- 2 files changed, 136 insertions(+), 118 deletions(-) diff --git a/python/plugins/sextante/ftools/ExportGeometryInfo.py b/python/plugins/sextante/ftools/ExportGeometryInfo.py index a6790e66958..a7146292c58 100644 --- a/python/plugins/sextante/ftools/ExportGeometryInfo.py +++ b/python/plugins/sextante/ftools/ExportGeometryInfo.py @@ -1,133 +1,151 @@ -from sextante.core.GeoAlgorithm import GeoAlgorithm import os.path + from PyQt4 import QtGui 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.parameters.ParameterVector import ParameterVector +from sextante.parameters.ParameterSelection import ParameterSelection + from sextante.outputs.OutputVector import OutputVector +from sextante.ftools import FToolsUtils as utils + class ExportGeometryInfo(GeoAlgorithm): INPUT = "INPUT" + METHOD = "CALC_METHOD" OUTPUT = "OUTPUT" + CALC_METHODS = ["Layer CRS", + "Project CRS", + "Ellipsoidal" + ] + def getIcon(self): return QtGui.QIcon(os.path.dirname(__file__) + "/icons/export_geometry.png") - def processAlgorithm(self, progress): - vlayer = QGisLayers.getObjectFromUri(self.getParameterValue(ExportGeometryInfo.INPUT)) - vprovider = vlayer.dataProvider() - allAttrs = vprovider.attributeIndexes() - vprovider.select( allAttrs ) - ( fields, index1, index2 ) = self.checkGeometryFields(vlayer) - writer = self.getOutputFromName(ExportGeometryInfo.OUTPUT).getVectorWriter(fields, vprovider.geometryType(), vprovider.crs() ) - inFeat = QgsFeature() - outFeat = QgsFeature() - inGeom = QgsGeometry() - nFeat = vprovider.featureCount() - nElement = 0 - while vprovider.nextFeature(inFeat): - progress.setPercentage(int(nElement/nFeat * 100)) - nElement += 1 - inGeom = inFeat.geometry() - ( attr1, attr2 ) = self.simpleMeasure( inGeom ) - outFeat.setGeometry( inGeom ) - atMap = inFeat.attributeMap() - outFeat.setAttributeMap( atMap ) - outFeat.addAttribute( index1, QVariant( attr1 ) ) - outFeat.addAttribute( index2, QVariant( attr2 ) ) - writer.addFeature( outFeat ) - del writer - - - def simpleMeasure( self, inGeom ): - if inGeom.wkbType() in (QGis.WKBPoint, QGis.WKBPoint25D): - pt = QgsPoint() - pt = inGeom.asPoint() - attr1 = pt.x() - attr2 = pt.y() - elif inGeom.wkbType() in (QGis.WKBMultiPoint, QGis.WKBMultiPoint25D): - pt = inGeom.asMultiPoint() - attr1 = pt[ 0 ].x() - attr2 = pt[ 0 ].y() - else: - 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 checkForField( self, L, e ): - e = QString( e ).toLower() - fieldRange = range( 0,len( L ) ) - for item in fieldRange: - if L[ item ].toLower() == e: - return True, item - return False, len( L ) - - def checkGeometryFields( self, vlayer ): - vprovider = vlayer.dataProvider() - nameList = [] - fieldList = vprovider.fields() - geomType = vlayer.geometryType() - for i in fieldList.keys(): - nameList.append( fieldList[ i ].name().toLower() ) - if geomType == QGis.Polygon: - plp = "Poly" - ( found, index1 ) = self.checkForField( nameList, "AREA" ) - if not found: - field = QgsField( "AREA", QVariant.Double, "double", 21, 6, "Polygon area" ) - index1 = len( fieldList.keys() ) - fieldList[ index1 ] = field - ( found, index2 ) = self.checkForField( nameList, "PERIMETER" ) - - if not found: - field = QgsField( "PERIMETER", QVariant.Double, "double", 21, 6, "Polygon perimeter" ) - index2 = len( fieldList.keys() ) - fieldList[ index2 ] = field - elif geomType == QGis.Line: - plp = "Line" - (found, index1) = self.checkForField(nameList, "LENGTH") - if not found: - field = QgsField("LENGTH", QVariant.Double, "double", 21, 6, "Line length" ) - index1 = len(fieldList.keys()) - fieldList[index1] = field - index2 = index1 - else: - plp = "Point" - (found, index1) = self.checkForField(nameList, "XCOORD") - if not found: - field = QgsField("XCOORD", QVariant.Double, "double", 21, 6, "Point x coordinate" ) - index1 = len(fieldList.keys()) - fieldList[index1] = field - (found, index2) = self.checkForField(nameList, "YCOORD") - if not found: - field = QgsField("YCOORD", QVariant.Double, "double", 21, 6, "Point y coordinate" ) - index2 = len(fieldList.keys()) - fieldList[index2] = field - return (fieldList, index1, index2) - - def defineCharacteristics(self): self.name = "Export/Add geometry columns" self.group = "Geometry tools" - self.addParameter(ParameterVector(ExportGeometryInfo.INPUT, "Input layer", ParameterVector.VECTOR_TYPE_ANY)) - self.addOutput(OutputVector(ExportGeometryInfo.OUTPUT, "Output layer")) - #========================================================= + + self.addParameter(ParameterVector(self.INPUT, "Input layer", ParameterVector.VECTOR_TYPE_ANY)) + self.addParameter(ParameterSelection(self.METHOD, "Calculate using", self.CALC_METHODS, 0)) + + self.addOutput(OutputVector(self.OUTPUT, "Output layer")) + + + def processAlgorithm(self, progress): + layer = QGisLayers.getObjectFromUri(self.getParameterValue(self.INPUT)) + method = self.getParameterValue(self.METHOD) + + output = self.getOutputValue(self.OUTPUT) + + provider = layer.dataProvider() + geometryType = layer.geometryType() + + layer.select(layer.pendingAllAttributesList()) + + idx1 = -1 + idx2 = -1 + fields = layer.pendingFields() + + if geometryType == QGis.Polygon: + idx1, fields = utils.findOrCreateField(layer, fields, "area", 21, 6) + idx2, fields = utils.findOrCreateField(layer, fields, "perimeter", 21, 6) + elif geometryType == QGis.Line: + idx1, fields = utils.findOrCreateField(layer, fields, "length", 21, 6) + idx2 = idx1 + else: + idx1, fields = utils.findOrCreateField(layer, fields, "xcoord", 21, 6) + idx2, fields = utils.findOrCreateField(layer, fields, "ycoord", 21, 6) + + writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, + provider.geometryType(), provider.crs()) + + ellips = None + crs = None + coordTransform = None + + # calculate with: + # 0 - layer CRS + # 1 - project CRS + # 2 - ellipsoidal + if method == 2: + settings = QSettings() + ellips = settings.value("/qgis/measure/ellipsoid", "WGS84").toString() + crs = layer.crs().srsid() + elif method == 1: + mapCRS = QGisLayers.iface.mapCanvas().mapRenderer().destinationCrs() + layCRS = layer.crs() + coordTransform = QgsCoordinateTransform(layCRS, mapCRS) + + inFeat = QgsFeature() + outFeat = QgsFeature() + inGeom = QgsGeometry() + + current = 0 + total = 100.0 / float(provider.featureCount()) + + while layer.nextFeature(inFeat): + inGeom = inFeat.geometry() + + if method == 1: + inGeom.transform(coordTransform) + + (attr1, attr2) = self.simpleMeasure(inGeom, method, ellips, crs) + + outFeat.setGeometry(inGeom) + atMap = inFeat.attributeMap() + outFeat.setAttributeMap(atMap) + outFeat.addAttribute(idx1, QVariant(attr1)) + outFeat.addAttribute(idx2, QVariant(attr2)) + writer.addFeature( outFeat ) + + current += 1 + 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.setProjectionsEnabled(True) + + attr1 = measure.measure(geom) + if geom.type() == QGis.Polygon: + attr2 = self.perimMeasure(geom, measure) + else: + attr2 = attr1 + + 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 diff --git a/python/plugins/sextante/ftools/FToolsUtils.py b/python/plugins/sextante/ftools/FToolsUtils.py index 5de4f78ff03..fd1676d493b 100644 --- a/python/plugins/sextante/ftools/FToolsUtils.py +++ b/python/plugins/sextante/ftools/FToolsUtils.py @@ -7,8 +7,8 @@ def createSpatialIndex(provider): idx = QgsSpatialIndex() provider.rewind() provider.select() - while provider.nextFeature( ft ): - idx.insertFeature( ft ) + while provider.nextFeature(ft): + idx.insertFeature(ft) return idx def createUniqueFieldName(fieldName, fieldList): @@ -37,7 +37,7 @@ def createUniqueFieldName(fieldName, fieldList): return shortName -def findOrCreateField(layer, fieldList, fieldName, fieldLen = 24, fieldPrec = 15): +def findOrCreateField(layer, fieldList, fieldName, fieldLen=24, fieldPrec=15): idx = layer.fieldNameIndex(fieldName) if idx == -1: idx = len(fieldList)