2013-02-23 21:43:17 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
"""
|
|
|
|
***************************************************************************
|
|
|
|
vector.py
|
|
|
|
---------------------
|
|
|
|
Date : February 2013
|
|
|
|
Copyright : (C) 2013 by Victor Olaya
|
|
|
|
Email : volayaf at gmail dot com
|
|
|
|
***************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
***************************************************************************
|
|
|
|
"""
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-02-23 21:43:17 +01:00
|
|
|
__author__ = 'Victor Olaya'
|
|
|
|
__date__ = 'February 2013'
|
|
|
|
__copyright__ = '(C) 2013, Victor Olaya'
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-02-23 21:43:17 +01:00
|
|
|
# This will get replaced with a git SHA1 when you do a git archive
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-02-23 21:43:17 +01:00
|
|
|
__revision__ = '$Format:%H$'
|
|
|
|
|
2013-11-28 12:57:45 +01:00
|
|
|
import uuid
|
|
|
|
|
2013-09-11 19:32:38 +02:00
|
|
|
from PyQt4.QtCore import *
|
2013-10-01 20:52:22 +03:00
|
|
|
from qgis.core import *
|
|
|
|
from processing.core.ProcessingConfig import ProcessingConfig
|
|
|
|
|
2013-02-16 00:23:56 +01:00
|
|
|
|
2013-09-12 13:19:00 +02:00
|
|
|
def features(layer):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""This returns an iterator over features in a vector layer,
|
|
|
|
considering the selection that might exist in the layer, and the
|
|
|
|
configuration that indicates whether to use only selected feature
|
|
|
|
or all of them.
|
|
|
|
|
|
|
|
This should be used by algorithms instead of calling the QGis API
|
|
|
|
directly, to ensure a consistent behaviour across algorithms.
|
|
|
|
"""
|
|
|
|
class Features:
|
|
|
|
|
2013-09-12 13:19:00 +02:00
|
|
|
def __init__(self, layer):
|
|
|
|
self.layer = layer
|
2013-10-01 20:52:22 +03:00
|
|
|
self.selection = False
|
2013-11-24 16:31:00 +01:00
|
|
|
self.iter = layer.getFeatures()
|
2013-09-12 13:19:00 +02:00
|
|
|
if ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED):
|
2013-11-06 00:15:19 +01:00
|
|
|
selected = layer.selectedFeatures()
|
|
|
|
if len(selected) > 0:
|
2013-09-12 13:19:00 +02:00
|
|
|
self.selection = True
|
2013-11-06 00:15:19 +01:00
|
|
|
self.iter = iter(selected)
|
2013-09-17 12:33:57 +02:00
|
|
|
|
2013-09-12 13:19:00 +02:00
|
|
|
def __iter__(self):
|
2013-11-06 00:15:19 +01:00
|
|
|
return self.iter
|
2013-09-17 12:33:57 +02:00
|
|
|
|
2013-09-12 13:19:00 +02:00
|
|
|
def __len__(self):
|
|
|
|
if self.selection:
|
|
|
|
return int(self.layer.selectedFeatureCount())
|
|
|
|
else:
|
|
|
|
return int(self.layer.featureCount())
|
2013-09-17 12:33:57 +02:00
|
|
|
|
2013-09-12 13:19:00 +02:00
|
|
|
return Features(layer)
|
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-09-12 13:19:00 +02:00
|
|
|
def uniqueValues(layer, attribute):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Returns a list of unique values for a given attribute.
|
|
|
|
|
|
|
|
Attribute can be defined using a field names or a zero-based
|
|
|
|
field index. It considers the existing selection.
|
|
|
|
"""
|
2013-04-10 15:03:17 +02:00
|
|
|
values = []
|
|
|
|
fieldIndex = resolveFieldIndex(layer, attribute)
|
2013-09-12 13:19:00 +02:00
|
|
|
feats = features(layer)
|
|
|
|
for feat in feats:
|
2013-04-10 15:03:17 +02:00
|
|
|
if feat.attributes()[fieldIndex] not in values:
|
|
|
|
values.append(feat.attributes()[fieldIndex])
|
|
|
|
return values
|
2013-02-16 00:23:56 +01:00
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-04-10 15:03:17 +02:00
|
|
|
def resolveFieldIndex(layer, attr):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""This method takes an object and returns the index field it
|
|
|
|
refers to in a layer. If the passed object is an integer, it
|
|
|
|
returns the same integer value. If the passed value is not an
|
|
|
|
integer, it returns the field whose name is the string
|
2013-04-10 15:03:17 +02:00
|
|
|
representation of the passed object.
|
2013-10-01 20:52:22 +03:00
|
|
|
|
|
|
|
Ir raises an exception if the int value is larger than the number
|
|
|
|
of fields, or if the passed object does not correspond to any
|
|
|
|
field.
|
|
|
|
"""
|
2013-04-10 15:03:17 +02:00
|
|
|
if isinstance(attr, int):
|
|
|
|
return attr
|
|
|
|
else:
|
|
|
|
index = layer.fieldNameIndex(unicode(attr))
|
2013-02-16 00:23:56 +01:00
|
|
|
if index == -1:
|
|
|
|
raise ValueError('Wrong field name')
|
2013-04-15 07:16:20 +02:00
|
|
|
return index
|
2013-04-10 15:03:17 +02:00
|
|
|
|
|
|
|
|
|
|
|
def values(layer, *attributes):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Returns the values in the attributes table of a vector layer,
|
|
|
|
for the passed fields.
|
|
|
|
|
2013-04-10 15:03:17 +02:00
|
|
|
Field can be passed as field names or as zero-based field indices.
|
|
|
|
Returns a dict of lists, with the passed field identifiers as keys.
|
2013-06-03 21:25:22 +02:00
|
|
|
It considers the existing selection.
|
2013-10-01 20:52:22 +03:00
|
|
|
|
|
|
|
It assummes fields are numeric or contain values that can be parsed
|
|
|
|
to a number.
|
|
|
|
"""
|
2013-04-10 15:03:17 +02:00
|
|
|
ret = {}
|
|
|
|
for attr in attributes:
|
|
|
|
index = resolveFieldIndex(layer, attr)
|
|
|
|
values = []
|
2013-09-12 13:19:00 +02:00
|
|
|
feats = features(layer)
|
|
|
|
for feature in feats:
|
2013-02-16 00:23:56 +01:00
|
|
|
try:
|
2013-06-03 21:25:22 +02:00
|
|
|
v = float(feature.attributes()[index])
|
2013-02-16 00:23:56 +01:00
|
|
|
values.append(v)
|
|
|
|
except:
|
|
|
|
values.append(None)
|
2013-10-01 20:52:22 +03:00
|
|
|
ret[attr] = values
|
2013-02-16 00:23:56 +01:00
|
|
|
return ret
|
2013-02-28 22:08:32 +01:00
|
|
|
|
2013-10-22 18:42:52 +01:00
|
|
|
def testForUniqueness( fieldList1, fieldList2 ):
|
|
|
|
'''Returns a modified version of fieldList2, removing naming
|
|
|
|
collisions with fieldList1.'''
|
|
|
|
changed = True
|
|
|
|
while changed:
|
|
|
|
changed = False
|
|
|
|
for i in range(0,len(fieldList1)):
|
|
|
|
for j in range(0,len(fieldList2)):
|
|
|
|
if fieldList1[i].name() == fieldList2[j].name():
|
|
|
|
field = fieldList2[j]
|
|
|
|
name = createUniqueFieldName( field.name(), fieldList1 )
|
|
|
|
fieldList2[j] = QgsField(name, field.type(), len=field.length(), prec=field.precision(), comment=field.comment())
|
|
|
|
changed = True
|
|
|
|
return fieldList2
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-04-10 15:03:17 +02:00
|
|
|
def spatialindex(layer):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Creates a spatial index for the passed vector layer.
|
|
|
|
"""
|
2013-04-10 15:03:17 +02:00
|
|
|
idx = QgsSpatialIndex()
|
2013-09-12 13:19:00 +02:00
|
|
|
feats = features(layer)
|
|
|
|
for ft in feats:
|
2013-04-10 15:03:17 +02:00
|
|
|
idx.insertFeature(ft)
|
|
|
|
return idx
|
|
|
|
|
2013-09-11 19:32:38 +02:00
|
|
|
|
|
|
|
def createUniqueFieldName(fieldName, fieldList):
|
2013-12-29 14:35:11 +02:00
|
|
|
def nextname(name):
|
|
|
|
num = 1
|
|
|
|
while True:
|
|
|
|
returnname ='{name}_{num}'.format(name=name[:8], num=num)
|
|
|
|
yield returnname
|
|
|
|
num += 1
|
2013-09-11 19:32:38 +02:00
|
|
|
|
2013-12-29 14:35:11 +02:00
|
|
|
def found(name):
|
|
|
|
return any(f.name() == name for f in fieldList)
|
2013-09-11 19:32:38 +02:00
|
|
|
|
2013-12-29 14:35:11 +02:00
|
|
|
shortName = fieldName[:10]
|
2013-09-11 19:32:38 +02:00
|
|
|
|
2013-12-29 14:35:11 +02:00
|
|
|
if not fieldList:
|
2013-09-11 19:32:38 +02:00
|
|
|
return shortName
|
|
|
|
|
2013-12-29 14:35:11 +02:00
|
|
|
if not found(shortName):
|
|
|
|
return shortName
|
2013-09-11 19:32:38 +02:00
|
|
|
|
2013-12-29 14:35:11 +02:00
|
|
|
for newname in nextname(shortName):
|
|
|
|
if not found(newname):
|
|
|
|
return newname
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-09-11 19:32:38 +02:00
|
|
|
def findOrCreateField(layer, fieldList, fieldName, fieldLen=24, fieldPrec=15):
|
|
|
|
idx = layer.fieldNameIndex(fieldName)
|
|
|
|
if idx == -1:
|
|
|
|
fn = createUniqueFieldName(fieldName, fieldList)
|
2013-10-01 20:52:22 +03:00
|
|
|
field = QgsField(fn, QVariant.Double, '', fieldLen, fieldPrec)
|
2013-09-11 19:32:38 +02:00
|
|
|
idx = len(fieldList)
|
|
|
|
fieldList.append(field)
|
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
return (idx, fieldList)
|
|
|
|
|
2013-09-11 19:32:38 +02:00
|
|
|
|
|
|
|
def extractPoints(geom):
|
|
|
|
points = []
|
2013-10-01 20:52:22 +03:00
|
|
|
if geom.type() == QGis.Point:
|
2013-09-11 19:32:38 +02:00
|
|
|
if geom.isMultipart():
|
|
|
|
points = geom.asMultiPoint()
|
|
|
|
else:
|
|
|
|
points.append(geom.asPoint())
|
|
|
|
elif geom.type() == QGis.Line:
|
|
|
|
if geom.isMultipart():
|
|
|
|
lines = geom.asMultiPolyline()
|
|
|
|
for line in lines:
|
|
|
|
points.extend(line)
|
|
|
|
else:
|
|
|
|
points = geom.asPolyline()
|
|
|
|
elif geom.type() == QGis.Polygon:
|
|
|
|
if geom.isMultipart():
|
|
|
|
polygons = geom.asMultiPolygon()
|
|
|
|
for poly in polygons:
|
|
|
|
for line in poly:
|
|
|
|
points.extend(line)
|
|
|
|
else:
|
|
|
|
polygon = geom.asPolygon()
|
|
|
|
for line in polygon:
|
|
|
|
points.extend(line)
|
|
|
|
|
|
|
|
return points
|
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-09-11 19:32:38 +02:00
|
|
|
def simpleMeasure(geom, method=0, ellips=None, crs=None):
|
2013-10-01 20:52:22 +03:00
|
|
|
# Method defines calculation type:
|
2013-09-11 19:32:38 +02:00
|
|
|
# 0 - layer CRS
|
|
|
|
# 1 - project CRS
|
|
|
|
# 2 - ellipsoidal
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-09-11 19:32:38 +02:00
|
|
|
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 = None
|
|
|
|
|
|
|
|
return (attr1, attr2)
|
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-09-11 19:32:38 +02:00
|
|
|
def getUniqueValues(layer, fieldIndex):
|
|
|
|
values = []
|
2013-09-12 13:19:00 +02:00
|
|
|
feats = features(layer)
|
|
|
|
for feat in feats:
|
2013-09-11 19:32:38 +02:00
|
|
|
if feat.attributes()[fieldIndex] not in values:
|
|
|
|
values.append(feat.attributes()[fieldIndex])
|
|
|
|
return values
|
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-09-11 19:32:38 +02:00
|
|
|
def getUniqueValuesCount(layer, fieldIndex):
|
|
|
|
return len(getUniqueValues(layer, fieldIndex))
|
|
|
|
|
2013-10-01 20:52:22 +03:00
|
|
|
|
2013-09-11 19:32:38 +02:00
|
|
|
def combineVectorFields(layerA, layerB):
|
2013-10-01 20:52:22 +03:00
|
|
|
"""Create single field map from two input field maps.
|
|
|
|
"""
|
2013-09-11 19:32:38 +02:00
|
|
|
fields = []
|
2014-07-05 13:38:25 +09:00
|
|
|
fieldsA = layerA.pendingFields()
|
2013-09-11 19:32:38 +02:00
|
|
|
fields.extend(fieldsA)
|
|
|
|
namesA = [unicode(f.name()).lower() for f in fieldsA]
|
2014-07-05 13:38:25 +09:00
|
|
|
fieldsB = layerB.pendingFields()
|
2013-09-11 19:32:38 +02:00
|
|
|
for field in fieldsB:
|
|
|
|
name = unicode(field.name()).lower()
|
|
|
|
if name in namesA:
|
2013-10-01 20:52:22 +03:00
|
|
|
idx = 2
|
|
|
|
newName = name + '_' + unicode(idx)
|
2013-09-11 19:32:38 +02:00
|
|
|
while newName in namesA:
|
|
|
|
idx += 1
|
2013-10-01 20:52:22 +03:00
|
|
|
newName = name + '_' + unicode(idx)
|
2013-09-11 19:32:38 +02:00
|
|
|
field = QgsField(newName, field.type(), field.typeName())
|
|
|
|
fields.append(field)
|
|
|
|
|
|
|
|
return fields
|
2013-11-28 12:57:45 +01:00
|
|
|
|
|
|
|
|
2014-03-25 19:51:49 +02:00
|
|
|
def duplicateInMemory(layer, newName='', addToRegistry=False):
|
|
|
|
"""Return a memory copy of a layer
|
2013-11-28 12:57:45 +01:00
|
|
|
|
2014-03-25 19:51:49 +02:00
|
|
|
layer: QgsVectorLayer that shall be copied to memory.
|
|
|
|
new_name: The name of the copied layer.
|
|
|
|
add_to_registry: if True, the new layer will be added to the QgsMapRegistry
|
2013-11-28 12:57:45 +01:00
|
|
|
|
2014-03-25 19:51:49 +02:00
|
|
|
Returns an in-memory copy of a layer.
|
2013-11-28 12:57:45 +01:00
|
|
|
"""
|
2014-03-25 19:51:49 +02:00
|
|
|
if newName is '':
|
|
|
|
newName = layer.name() + ' (Memory)'
|
2013-11-28 12:57:45 +01:00
|
|
|
|
|
|
|
if layer.type() == QgsMapLayer.VectorLayer:
|
2014-03-25 19:51:49 +02:00
|
|
|
geomType = layer.geometryType()
|
|
|
|
if geomType == QGis.Point:
|
|
|
|
strType = 'Point'
|
|
|
|
elif geomType == QGis.Line:
|
|
|
|
strType = 'Line'
|
|
|
|
elif geomType == QGis.Polygon:
|
|
|
|
strType = 'Polygon'
|
2013-11-28 12:57:45 +01:00
|
|
|
else:
|
2014-03-25 19:51:49 +02:00
|
|
|
raise RuntimeError('Layer is whether Point nor Line nor Polygon')
|
2013-11-28 12:57:45 +01:00
|
|
|
else:
|
|
|
|
raise RuntimeError('Layer is not a VectorLayer')
|
|
|
|
|
|
|
|
crs = layer.crs().authid().lower()
|
2014-03-25 19:51:49 +02:00
|
|
|
myUuid = str(uuid.uuid4())
|
|
|
|
uri = '%s?crs=%s&index=yes&uuid=%s' % (strType, crs, myUuid)
|
|
|
|
memLayer = QgsVectorLayer(uri, newName, 'memory')
|
|
|
|
memProvider = memLayer.dataProvider()
|
2013-11-28 12:57:45 +01:00
|
|
|
|
|
|
|
provider = layer.dataProvider()
|
2014-03-25 19:51:49 +02:00
|
|
|
fields = provider.fields().toList()
|
|
|
|
memProvider.addAttributes(fields)
|
|
|
|
memLayer.updateFields()
|
2013-11-28 12:57:45 +01:00
|
|
|
|
|
|
|
for ft in provider.getFeatures():
|
2014-03-25 19:51:49 +02:00
|
|
|
memProvider.addFeatures([ft])
|
2013-11-28 12:57:45 +01:00
|
|
|
|
2014-03-25 19:51:49 +02:00
|
|
|
if addToRegistry:
|
|
|
|
if memLayer.isValid():
|
|
|
|
QgsMapLayerRegistry.instance().addMapLayer(memLayer)
|
2013-11-28 12:57:45 +01:00
|
|
|
else:
|
|
|
|
raise RuntimeError('Layer invalid')
|
|
|
|
|
2014-04-25 12:39:06 +03:00
|
|
|
return memLayer
|
|
|
|
|
|
|
|
def checkMinDistance(point, index, distance, points):
|
|
|
|
"""Check if distance from given point to all other points is greater
|
|
|
|
than given value.
|
|
|
|
"""
|
|
|
|
if distance == 0:
|
|
|
|
return True
|
|
|
|
|
|
|
|
neighbors = index.nearestNeighbor(point, 1)
|
|
|
|
if len(neighbors) == 0:
|
|
|
|
return True
|
|
|
|
|
|
|
|
if neighbors[0] in points:
|
|
|
|
np = points[neighbors[0]]
|
|
|
|
if np.sqrDist(point) < (distance * distance):
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
from PyQt4.QtCore import *
|
|
|
|
from qgis.core import *
|
|
|
|
|
2014-08-03 16:46:13 +02:00
|
|
|
GEOM_TYPE_MAP = {
|
|
|
|
QGis.WKBPoint: 'Point',
|
|
|
|
QGis.WKBLineString: 'LineString',
|
|
|
|
QGis.WKBPolygon: 'Polygon',
|
|
|
|
QGis.WKBMultiPoint: 'MultiPoint',
|
|
|
|
QGis.WKBMultiLineString: 'MultiLineString',
|
|
|
|
QGis.WKBMultiPolygon: 'MultiPolygon',
|
|
|
|
}
|
|
|
|
|
|
|
|
TYPE_MAP = {
|
|
|
|
str : QVariant.String,
|
|
|
|
float: QVariant.Double,
|
|
|
|
int: QVariant.Int
|
|
|
|
}
|
|
|
|
|
2014-08-28 09:33:05 +03:00
|
|
|
def _fieldName(f):
|
2014-08-03 16:46:13 +02:00
|
|
|
if isinstance(f, basestring):
|
|
|
|
return f
|
|
|
|
return f.name()
|
|
|
|
|
2014-08-28 09:33:05 +03:00
|
|
|
def _toQgsField(f):
|
2014-08-03 16:46:13 +02:00
|
|
|
if isinstance(f, QgsField):
|
|
|
|
return f
|
|
|
|
return QgsField(f[0], TYPE_MAP.get(f[1], QVariant.String))
|
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
class VectorWriter:
|
|
|
|
|
|
|
|
MEMORY_LAYER_PREFIX = 'memory:'
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, fileName, encoding, fields, geometryType,
|
|
|
|
crs, options=None):
|
|
|
|
self.fileName = fileName
|
|
|
|
self.isMemory = False
|
|
|
|
self.memLayer = None
|
|
|
|
self.writer = None
|
|
|
|
|
|
|
|
if encoding is None:
|
|
|
|
settings = QSettings()
|
|
|
|
encoding = settings.value('/Processing/encoding', 'System', type=str)
|
|
|
|
|
|
|
|
if self.fileName.startswith(self.MEMORY_LAYER_PREFIX):
|
|
|
|
self.isMemory = True
|
|
|
|
|
2014-08-03 16:46:13 +02:00
|
|
|
uri = self.GEOM_TYPE_MAP[geometryType]
|
2014-07-14 14:19:09 +02:00
|
|
|
if crs.isValid():
|
|
|
|
uri += '?crs=' + crs.authid() + '&'
|
2014-08-03 16:46:13 +02:00
|
|
|
fieldsdesc = ['field=' + _fieldName(f) for f in fields]
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
fieldsstring = '&'.join(fieldsdesc)
|
|
|
|
uri += fieldsstring
|
|
|
|
self.memLayer = QgsVectorLayer(uri, self.fileName, 'memory')
|
|
|
|
self.writer = self.memLayer.dataProvider()
|
|
|
|
else:
|
|
|
|
formats = QgsVectorFileWriter.supportedFiltersAndFormats()
|
|
|
|
OGRCodes = {}
|
|
|
|
for (key, value) in formats.items():
|
|
|
|
extension = unicode(key)
|
|
|
|
extension = extension[extension.find('*.') + 2:]
|
|
|
|
extension = extension[:extension.find(' ')]
|
|
|
|
OGRCodes[extension] = value
|
|
|
|
|
|
|
|
extension = self.fileName[self.fileName.rfind('.') + 1:]
|
|
|
|
if extension not in OGRCodes:
|
|
|
|
extension = 'shp'
|
|
|
|
self.filename = self.filename + 'shp'
|
|
|
|
|
|
|
|
qgsfields = QgsFields()
|
|
|
|
for field in fields:
|
2014-08-03 16:46:13 +02:00
|
|
|
qgsfields.append(_toQgsField(field))
|
2014-07-14 14:19:09 +02:00
|
|
|
|
|
|
|
self.writer = QgsVectorFileWriter(self.fileName, encoding,
|
|
|
|
qgsfields, geometryType, crs, OGRCodes[extension])
|
|
|
|
|
|
|
|
def addFeature(self, feature):
|
|
|
|
if self.isMemory:
|
|
|
|
self.writer.addFeatures([feature])
|
|
|
|
else:
|
|
|
|
self.writer.addFeature(feature)
|
2014-08-03 16:46:13 +02:00
|
|
|
|
2014-07-14 14:19:09 +02:00
|
|
|
import csv
|
|
|
|
import codecs
|
|
|
|
import cStringIO
|
|
|
|
|
|
|
|
|
|
|
|
class TableWriter:
|
|
|
|
|
|
|
|
def __init__(self, fileName, encoding, fields):
|
|
|
|
self.fileName = fileName
|
|
|
|
if not self.fileName.lower().endswith('csv'):
|
|
|
|
self.fileName += '.csv'
|
|
|
|
|
|
|
|
self.encoding = encoding
|
|
|
|
if self.encoding is None or encoding == 'System':
|
|
|
|
self.encoding = 'utf-8'
|
|
|
|
|
|
|
|
with open(self.fileName, 'wb') as csvFile:
|
|
|
|
self.writer = UnicodeWriter(csvFile, encoding=self.encoding)
|
|
|
|
if len(fields) != 0:
|
|
|
|
self.writer.writerow(fields)
|
|
|
|
|
|
|
|
def addRecord(self, values):
|
|
|
|
with open(self.fileName, 'ab') as csvFile:
|
|
|
|
self.writer = UnicodeWriter(csvFile, encoding=self.encoding)
|
|
|
|
self.writer.writerow(values)
|
|
|
|
|
|
|
|
def addRecords(self, records):
|
|
|
|
with open(self.fileName, 'ab') as csvFile:
|
|
|
|
self.writer = UnicodeWriter(csvFile, encoding=self.encoding)
|
|
|
|
self.writer.writerows(records)
|
|
|
|
|
|
|
|
|
|
|
|
class UnicodeWriter:
|
|
|
|
|
|
|
|
def __init__(self, f, dialect=csv.excel, encoding='utf-8', **kwds):
|
|
|
|
self.queue = cStringIO.StringIO()
|
|
|
|
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
|
|
|
|
self.stream = f
|
|
|
|
self.encoder = codecs.getincrementalencoder(encoding)()
|
|
|
|
|
|
|
|
def writerow(self, row):
|
|
|
|
row = map(unicode, row)
|
|
|
|
try:
|
|
|
|
self.writer.writerow([s.encode('utf-8') for s in row])
|
|
|
|
except:
|
|
|
|
self.writer.writerow(row)
|
|
|
|
data = self.queue.getvalue()
|
|
|
|
data = data.decode('utf-8')
|
|
|
|
data = self.encoder.encode(data)
|
|
|
|
self.stream.write(data)
|
|
|
|
self.queue.truncate(0)
|
|
|
|
|
|
|
|
def writerows(self, rows):
|
|
|
|
for row in rows:
|
2014-08-03 16:46:13 +02:00
|
|
|
self.writerow(row)
|