Skip to content

Commit

Permalink
[sextante] fix Advaced Python Calculator, add ability to select field
Browse files Browse the repository at this point in the history
type, lenght and precision
  • Loading branch information
alexbruy committed Apr 11, 2013
1 parent f59e21c commit 4b06df0
Showing 1 changed file with 40 additions and 29 deletions.
69 changes: 40 additions & 29 deletions python/plugins/sextante/algs/FieldPyculator.py
Expand Up @@ -23,28 +23,40 @@
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

from sextante.core.GeoAlgorithm import GeoAlgorithm
from sextante.outputs.OutputVector import OutputVector
from sextante.parameters.ParameterVector import ParameterVector
from qgis.core import *
import sys

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from sextante.parameters.ParameterString import ParameterString

from qgis.core import *

from sextante.core.GeoAlgorithm import GeoAlgorithm
from sextante.core.QGisLayers import QGisLayers
from sextante.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
import sys

from sextante.parameters.ParameterVector import ParameterVector
from sextante.parameters.ParameterString import ParameterString
from sextante.parameters.ParameterNumber import ParameterNumber
from sextante.parameters.ParameterSelection import ParameterSelection

from sextante.outputs.OutputVector import OutputVector


class FieldsPyculator(GeoAlgorithm):

INPUT_LAYER = "INPUT_LAYER"
USE_SELECTED = "USE_SELECTED"
FIELD_NAME = "FIELD_NAME"
FIELD_TYPE = "FIELD_TYPE"
FIELD_LENGTH = "FIELD_LENGTH"
FIELD_PRECISION = "FIELD_PRECISION"
GLOBAL = "GLOBAL"
FORMULA = "FORMULA"
OUTPUT_LAYER ="OUTPUT_LAYER"
RESULT_VAR_NAME = "value"

TYPE_NAMES = ["Integer", "Float", "String"]
TYPES = [QVariant.Int, QVariant.Double, QVariant.String]


#===========================================================================
# def getIcon(self):
# return QtGui.QIcon(os.path.dirname(__file__) + "/../images/qgis.png")
Expand All @@ -55,21 +67,27 @@ def defineCharacteristics(self):
self.group = "Vector table tools"
self.addParameter(ParameterVector(self.INPUT_LAYER, "Input layer", ParameterVector.VECTOR_TYPE_ANY, False))
self.addParameter(ParameterString(self.FIELD_NAME, "Result field name", "NewField"))
self.addParameter(ParameterSelection(self.FIELD_TYPE, "Field type", self.TYPE_NAMES))
self.addParameter(ParameterNumber(self.FIELD_LENGTH, "Field lenght", 1, 255, 10))
self.addParameter(ParameterNumber(self.FIELD_PRECISION, "Field precision", 0, 10, 0))
self.addParameter(ParameterString(self.GLOBAL, "Global expression", multiline = True))
self.addParameter(ParameterString(self.FORMULA, "Formula", "value = ", multiline = True))
self.addOutput(OutputVector(self.OUTPUT_LAYER, "Output layer"))


def processAlgorithm(self, progress):
fieldname = self.getParameterValue(self.FIELD_NAME)
fieldName = self.getParameterValue(self.FIELD_NAME)
fieldType = self.getParameterValue(self.FIELD_TYPE)
fieldLength = self.getParameterValue(self.FIELD_LENGTH)
fieldPrecision = self.getParameterValue(self.FIELD_PRECISION)
code = self.getParameterValue(self.FORMULA)
globalExpression = self.getParameterValue(self.GLOBAL)
output = self.getOutputFromName(self.OUTPUT_LAYER)

layer = QGisLayers.getObjectFromUri(self.getParameterValue(self.INPUT_LAYER))
vprovider = layer.dataProvider()
fields = vprovider.fields()
fields.append(QgsField(fieldname, QVariant.Double))
writer = output.getVectorWriter(fields, vprovider.geometryType(), layer.crs() )
provider = layer.dataProvider()
fields = provider.fields()
fields.append(QgsField(fieldName, self.TYPES[fieldType], "", fieldLength, fieldPrecision))
writer = output.getVectorWriter(fields, provider.geometryType(), layer.crs())
outFeat = QgsFeature()
new_ns = {}

Expand All @@ -84,22 +102,21 @@ def processAlgorithm(self, progress):
(unicode(sys.exc_info()[0].__name__), unicode(sys.exc_info()[1])))

#replace all fields tags
fields = vprovider.fields()
fields = provider.fields()
num = 0
for field in fields:
field_name = unicode(field.name())
replval = '__attr[' + str(num) + ']'
code = code.replace("<"+field_name+">",replval)
code = code.replace("<" + field_name + ">", replval)
num += 1

#replace all special vars
code = code.replace('$id','__id')
code = code.replace('$geom','__geom')
code = code.replace('$id', '__id')
code = code.replace('$geom', '__geom')
need_id = code.find("__id") != -1
need_geom = code.find("__geom") != -1
need_attrs = code.find("__attr") != -1


#compile
try:
bytecode = compile(code, '<string>', 'exec')
Expand All @@ -114,7 +131,7 @@ def processAlgorithm(self, progress):
nElement = 1
for feat in features:
progress.setPercentage(int((100 * nElement)/nFeatures))
attrMap = feat.attributes()
attrs = feat.attributes()
feat_id = feat.id()

#add needed vars
Expand All @@ -126,14 +143,13 @@ def processAlgorithm(self, progress):
new_ns['__geom'] = geom

if need_attrs:
pyattrs = [self.Qvar2py(a) for a in attrMap]
pyattrs = [self.Qvar2py(a) for a in attrs]
new_ns['__attr'] = pyattrs

#clear old result
if new_ns.has_key(self.RESULT_VAR_NAME):
del new_ns[self.RESULT_VAR_NAME]


#exec
#try:
exec bytecode in new_ns
Expand All @@ -153,17 +169,15 @@ def processAlgorithm(self, progress):
"Field code block does not return '%s1' variable! Please declare this variable in your code!" %
self.RESULT_VAR_NAME)


#write feature
nElement += 1
outFeat.setGeometry( feat.geometry() )
attrMap.append(QVariant(new_ns[self.RESULT_VAR_NAME]))
outFeat.setAttributeMap( attrMap )
attrs.append(QVariant(new_ns[self.RESULT_VAR_NAME]))
outFeat.setAttributes(attrs)
writer.addFeature(outFeat)

del writer


def Qvar2py(self,qv):
if qv.type() == 2:
return qv.toInt()[0]
Expand All @@ -173,9 +187,6 @@ def Qvar2py(self,qv):
return qv.toDouble()[0]
return None


def checkParameterValuesBeforeExecuting(self):
##TODO check that formula is correct and fields exist
pass


0 comments on commit 4b06df0

Please sign in to comment.