review Export geometry info tool, sync with master

This commit is contained in:
Alexander Bruy 2012-10-01 20:48:06 +03:00
parent 1a67b91c4c
commit a6418d6502
2 changed files with 136 additions and 118 deletions

View File

@ -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

View File

@ -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)