Skip to content
Permalink
Browse files

Port Convert Geometry Type to new API

Includes partial support for Z/M types (values are lost during
conversion, but at least 2d geometries are exported)

TODO: full support for Z/M/curves
  • Loading branch information
nyalldawson committed Aug 20, 2017
1 parent 4d242c5 commit 51f8b1a2bbf96acd32c038dcc81781df7fb7d1e5
@@ -29,13 +29,11 @@
QgsGeometry,
QgsFeatureSink,
QgsWkbTypes,
QgsApplication,
QgsProcessingUtils)
QgsProcessingException,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterEnum,
QgsProcessingParameterFeatureSink)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterSelection
from processing.core.outputs import OutputVector


class GeometryConvert(QgisAlgorithm):
@@ -56,12 +54,13 @@ def initAlgorithm(self, config=None):
self.tr('Multilinestrings'),
self.tr('Polygons')]

self.addParameter(ParameterVector(self.INPUT,
self.tr('Input layer')))
self.addParameter(ParameterSelection(self.TYPE,
self.tr('New geometry type'), self.types))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer')))
self.addParameter(QgsProcessingParameterEnum(self.TYPE,
self.tr('New geometry type'), options=self.types))

self.addOutput(OutputVector(self.OUTPUT, self.tr('Converted')))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT,
self.tr('Converted')))

def name(self):
return 'convertgeometrytype'
@@ -70,8 +69,8 @@ def displayName(self):
return self.tr('Convert geometry type')

def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
index = self.getParameterValue(self.TYPE)
source = self.parameterAsSource(parameters, self.INPUT, context)
index = self.parameterAsEnum(parameters, self.TYPE, context)

splitNodes = False
if index == 0:
@@ -88,107 +87,118 @@ def processAlgorithm(self, parameters, context, feedback):
else:
newType = QgsWkbTypes.Point

writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(layer.fields(), newType, layer.crs(), context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
source.fields(), newType, source.sourceCrs())

features = QgsProcessingUtils.getFeatures(layer, context)
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
features = source.getFeatures()
total = 100.0 / source.featureCount() if source.featureCount() else 0

for current, f in enumerate(features):
if feedback.isCanceled():
break

if not f.hasGeometry():
sink.addFeature(f, QgsFeatureSink.FastInsert)

geom = f.geometry()
geomType = geom.wkbType()

if geomType in [QgsWkbTypes.Point, QgsWkbTypes.Point25D]:
if QgsWkbTypes.geometryType(geomType) == QgsWkbTypes.PointGeometry and not QgsWkbTypes.isMultiType(geomType):
if newType == QgsWkbTypes.Point:
writer.addFeature(f, QgsFeatureSink.FastInsert)
sink.addFeature(f, QgsFeatureSink.FastInsert)
else:
raise GeoAlgorithmExecutionException(
raise QgsProcessingException(
self.tr('Cannot convert from {0} to {1}').format(geomType, newType))
elif geomType in [QgsWkbTypes.MultiPoint, QgsWkbTypes.MultiPoint25D]:
elif QgsWkbTypes.geometryType(geomType) == QgsWkbTypes.PointGeometry and QgsWkbTypes.isMultiType(geomType):
if newType == QgsWkbTypes.Point and splitNodes:
points = geom.asMultiPoint()
for p in points:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(QgsGeometry.fromPoint(p))
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.Point:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(geom.centroid())
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
else:
raise GeoAlgorithmExecutionException(
raise QgsProcessingException(
self.tr('Cannot convert from {0} to {1}').format(geomType, newType))
elif geomType in [QgsWkbTypes.LineString, QgsWkbTypes.LineString25D]:
elif QgsWkbTypes.geometryType(geomType) == QgsWkbTypes.LineGeometry and not QgsWkbTypes.isMultiType(geomType):
if newType == QgsWkbTypes.Point and splitNodes:
points = geom.asPolyline()
for p in points:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(QgsGeometry.fromPoint(p))
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.Point:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(geom.centroid())
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.LineString:
writer.addFeature(f, QgsFeatureSink.FastInsert)
sink.addFeature(f, QgsFeatureSink.FastInsert)
else:
raise GeoAlgorithmExecutionException(
raise QgsProcessingException(
self.tr('Cannot convert from {0} to {1}').format(geomType, newType))
elif geomType in [QgsWkbTypes.MultiLineString, QgsWkbTypes.MultiLineString25D]:
elif QgsWkbTypes.geometryType(geomType) == QgsWkbTypes.LineGeometry and QgsWkbTypes.isMultiType(
geomType):
if newType == QgsWkbTypes.Point and splitNodes:
lines = geom.asMultiPolyline()
for line in lines:
for p in line:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(QgsGeometry.fromPoint(p))
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.Point:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(geom.centroid())
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.LineString:
lines = geom.asMultiPolyline()
for line in lines:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(QgsGeometry.fromPolyline(line))
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.MultiLineString:
writer.addFeature(f, QgsFeatureSink.FastInsert)
sink.addFeature(f, QgsFeatureSink.FastInsert)
else:
raise GeoAlgorithmExecutionException(
raise QgsProcessingException(
self.tr('Cannot convert from {0} to {1}').format(geomType, newType))
elif geomType in [QgsWkbTypes.Polygon, QgsWkbTypes.Polygon25D]:
elif QgsWkbTypes.geometryType(geomType) == QgsWkbTypes.PolygonGeometry and not QgsWkbTypes.isMultiType(
geomType):
if newType == QgsWkbTypes.Point and splitNodes:
rings = geom.asPolygon()
for ring in rings:
for p in ring:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(QgsGeometry.fromPoint(p))
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.Point:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(geom.centroid())
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.MultiLineString:
rings = geom.asPolygon()
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(QgsGeometry.fromMultiPolyline(rings))
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.Polygon:
writer.addFeature(f, QgsFeatureSink.FastInsert)
sink.addFeature(f, QgsFeatureSink.FastInsert)
else:
raise GeoAlgorithmExecutionException(
raise QgsProcessingException(
self.tr('Cannot convert from {0} to {1}').format(geomType, newType))
elif geomType in [QgsWkbTypes.MultiPolygon, QgsWkbTypes.MultiPolygon25D]:
elif QgsWkbTypes.geometryType(
geomType) == QgsWkbTypes.PolygonGeometry and QgsWkbTypes.isMultiType(
geomType):
if newType == QgsWkbTypes.Point and splitNodes:
polygons = geom.asMultiPolygon()
for polygon in polygons:
@@ -197,32 +207,32 @@ def processAlgorithm(self, parameters, context, feedback):
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(QgsGeometry.fromPoint(p))
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.Point:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(geom.centroid())
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.LineString:
polygons = geom.asMultiPolygon()
for polygons in polygons:
for polygon in polygons:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(QgsGeometry.fromPolyline(polygon))
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType == QgsWkbTypes.Polygon:
polygons = geom.asMultiPolygon()
for polygon in polygons:
feat = QgsFeature()
feat.setAttributes(f.attributes())
feat.setGeometry(QgsGeometry.fromPolygon(polygon))
writer.addFeature(feat, QgsFeatureSink.FastInsert)
sink.addFeature(feat, QgsFeatureSink.FastInsert)
elif newType in [QgsWkbTypes.MultiLineString, QgsWkbTypes.MultiPolygon]:
writer.addFeature(f, QgsFeatureSink.FastInsert)
sink.addFeature(f, QgsFeatureSink.FastInsert)
else:
raise GeoAlgorithmExecutionException(
raise QgsProcessingException(
self.tr('Cannot convert from {0} to {1}').format(geomType, newType))

feedback.setProgress(int(current * total))

del writer
return {self.OUTPUT: dest_id}
@@ -78,6 +78,7 @@
from .FindProjection import FindProjection
from .FixedDistanceBuffer import FixedDistanceBuffer
from .FixGeometry import FixGeometry
from .GeometryConvert import GeometryConvert
from .GeometryByExpression import GeometryByExpression
from .Gridify import Gridify
from .GridLine import GridLine
@@ -171,7 +172,6 @@
# from .ExtractByLocation import ExtractByLocation
# from .SelectByLocation import SelectByLocation
# from .SpatialJoin import SpatialJoin
# from .GeometryConvert import GeometryConvert
# from .SelectByAttributeSum import SelectByAttributeSum

pluginPath = os.path.normpath(os.path.join(
@@ -190,7 +190,6 @@ def getAlgs(self):
# SelectByLocation(),
# ExtractByLocation(),
# SpatialJoin(),
# GeometryConvert(),
# SelectByAttributeSum()
# ]
algs = [AddTableField(),
@@ -232,6 +231,7 @@ def getAlgs(self):
FixedDistanceBuffer(),
FixGeometry(),
GeometryByExpression(),
GeometryConvert(),
Gridify(),
GridLine(),
GridPolygon(),
@@ -6,7 +6,7 @@
<GeometryType>1</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>5</FeatureCount>
<FeatureCount>6</FeatureCount>
<ExtentXMin>0.65385</ExtentXMin>
<ExtentXMax>8.00000</ExtentXMax>
<ExtentYMin>-1.00000</ExtentYMin>
@@ -41,6 +41,12 @@
<ogr:intval>0</ogr:intval>
</ogr:convert_poly_centroid>
</gml:featureMember>
<gml:featureMember>
<ogr:convert_poly_centroid fid="polys.4">
<ogr:intval>120</ogr:intval>
<ogr:floatval>-100291.43213</ogr:floatval>
</ogr:convert_poly_centroid>
</gml:featureMember>
<gml:featureMember>
<ogr:convert_poly_centroid fid="polys.5">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4.08045977011494,-0.218390804597701</gml:coordinates></gml:Point></ogr:geometryProperty>
@@ -6,7 +6,7 @@
<GeometryType>5</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>5</FeatureCount>
<FeatureCount>6</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>10.00000</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
@@ -41,6 +41,12 @@
<ogr:intval>0</ogr:intval>
</ogr:convert_poly_multiline>
</gml:featureMember>
<gml:featureMember>
<ogr:convert_poly_multiline fid="polys.4">
<ogr:intval>120</ogr:intval>
<ogr:floatval>-100291.43213</ogr:floatval>
</ogr:convert_poly_multiline>
</gml:featureMember>
<gml:featureMember>
<ogr:convert_poly_multiline fid="polys.5">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>3,2 6,1 6,-3 2,-1 2,2 3,2</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
@@ -6,7 +6,7 @@
<GeometryType>1</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>32</FeatureCount>
<FeatureCount>33</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>10.00000</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
@@ -204,6 +204,12 @@
<ogr:intval>0</ogr:intval>
</ogr:convert_poly_nodes>
</gml:featureMember>
<gml:featureMember>
<ogr:convert_poly_nodes fid="polys.4">
<ogr:intval>120</ogr:intval>
<ogr:floatval>-100291.43213</ogr:floatval>
</ogr:convert_poly_nodes>
</gml:featureMember>
<gml:featureMember>
<ogr:convert_poly_nodes fid="polys.5">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,2</gml:coordinates></gml:Point></ogr:geometryProperty>

0 comments on commit 51f8b1a

Please sign in to comment.
You can’t perform that action at this time.