mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Merge pull request #4950 from nyalldawson/algs
Port some more algs to new API
This commit is contained in:
commit
a5ddab6cc8
@ -242,7 +242,9 @@ qgis:generatepointspixelcentroidsinsidepolygons:
|
||||
|
||||
|
||||
qgis:hublines:
|
||||
This algorithm creates hub and spoke diagrams with lines drawn from points on the Spoke Point layer to matching points in the Hub Point layer.
|
||||
|
||||
Determination of which hub goes with each point is based on a match between the Hub ID field on the hub points and the Spoke ID field on the spoke points.
|
||||
|
||||
qgis:hypsometriccurves: >
|
||||
This algorithm computes hypsometric curves for an input Digital Elevation Model. Curves are produced as table files in an output folder specified by the user.
|
||||
@ -368,7 +370,9 @@ qgis:pointslayerfromtable: >
|
||||
The attributes table of the resulting layer will be the input table.
|
||||
|
||||
qgis:pointstopath:
|
||||
Converts a point layer to a line layer, by joining points in a defined order.
|
||||
|
||||
Points can be grouped by a field to output individual line features per group.
|
||||
|
||||
qgis:polarplot: >
|
||||
This algorithm generates a polar plot based on the value of an input vector layer.
|
||||
|
@ -34,15 +34,14 @@ from qgis.core import (QgsFeatureRequest,
|
||||
QgsFeature,
|
||||
QgsFeatureSink,
|
||||
QgsGeometry,
|
||||
QgsMessageLog,
|
||||
QgsProcessingUtils)
|
||||
QgsProcessingException,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterVectorLayer,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessing,
|
||||
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
|
||||
from processing.tools import dataobjects
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
@ -67,16 +66,17 @@ class EliminateSelection(QgisAlgorithm):
|
||||
super().__init__()
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.modes = [self.tr('Largest area'),
|
||||
self.modes = [self.tr('Largest Area'),
|
||||
self.tr('Smallest Area'),
|
||||
self.tr('Largest common boundary')]
|
||||
self.tr('Largest Common Boundary')]
|
||||
|
||||
self.addParameter(ParameterVector(self.INPUT,
|
||||
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_POLYGON]))
|
||||
self.addParameter(ParameterSelection(self.MODE,
|
||||
self.tr('Merge selection with the neighbouring polygon with the'),
|
||||
self.modes))
|
||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Eliminated'), datatype=[dataobjects.TYPE_VECTOR_POLYGON]))
|
||||
self.addParameter(QgsProcessingParameterVectorLayer(self.INPUT,
|
||||
self.tr('Input layer'), [QgsProcessing.TypeVectorPolygon]))
|
||||
self.addParameter(QgsProcessingParameterEnum(self.MODE,
|
||||
self.tr('Merge selection with the neighbouring polygon with the'),
|
||||
options=self.modes))
|
||||
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Eliminated'), QgsProcessing.TypeVectorPolygon))
|
||||
|
||||
def name(self):
|
||||
return 'eliminateselectedpolygons'
|
||||
@ -85,29 +85,32 @@ class EliminateSelection(QgisAlgorithm):
|
||||
return self.tr('Eliminate selected polygons')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
inLayer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
|
||||
boundary = self.getParameterValue(self.MODE) == self.MODE_BOUNDARY
|
||||
smallestArea = self.getParameterValue(self.MODE) == self.MODE_SMALLEST_AREA
|
||||
inLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
boundary = self.parameterAsEnum(parameters, self.MODE, context) == self.MODE_BOUNDARY
|
||||
smallestArea = self.parameterAsEnum(parameters, self.MODE, context) == self.MODE_SMALLEST_AREA
|
||||
|
||||
if inLayer.selectedFeatureCount() == 0:
|
||||
QgsMessageLog.logMessage(self.tr('{0}: (No selection in input layer "{1}")').format(self.displayName(), self.getParameterValue(self.INPUT)),
|
||||
self.tr('Processing'), QgsMessageLog.WARNING)
|
||||
feedback.reportError(self.tr('{0}: (No selection in input layer "{1}")').format(self.displayName(), parameters[self.INPUT]))
|
||||
|
||||
featToEliminate = []
|
||||
selFeatIds = inLayer.selectedFeatureIds()
|
||||
output = self.getOutputFromName(self.OUTPUT)
|
||||
writer = output.getVectorWriter(inLayer.fields(), inLayer.wkbType(), inLayer.crs(), context)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
inLayer.fields(), inLayer.wkbType(), inLayer.sourceCrs())
|
||||
|
||||
for aFeat in inLayer.getFeatures():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if aFeat.id() in selFeatIds:
|
||||
# Keep references to the features to eliminate
|
||||
featToEliminate.append(aFeat)
|
||||
else:
|
||||
# write the others to output
|
||||
writer.addFeature(aFeat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(aFeat, QgsFeatureSink.FastInsert)
|
||||
|
||||
# Delete all features to eliminate in processLayer
|
||||
processLayer = output.layer
|
||||
processLayer = QgsProcessingUtils.mapLayerFromString(dest_id, context)
|
||||
processLayer.startEditing()
|
||||
|
||||
# ANALYZE
|
||||
@ -129,6 +132,9 @@ class EliminateSelection(QgisAlgorithm):
|
||||
|
||||
# Iterate over the polygons to eliminate
|
||||
for i in range(len(featToEliminate)):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
feat = featToEliminate.pop()
|
||||
geom2Eliminate = feat.geometry()
|
||||
bbox = geom2Eliminate.boundingBox()
|
||||
@ -145,6 +151,9 @@ class EliminateSelection(QgisAlgorithm):
|
||||
engine.prepareGeometry()
|
||||
|
||||
while fit.nextFeature(selFeat):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
selGeom = selFeat.geometry()
|
||||
|
||||
if engine.intersects(selGeom.geometry()):
|
||||
@ -193,7 +202,7 @@ class EliminateSelection(QgisAlgorithm):
|
||||
if processLayer.changeGeometry(mergeWithFid, newGeom):
|
||||
madeProgress = True
|
||||
else:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
raise QgsProcessingException(
|
||||
self.tr('Could not replace geometry of feature with id {0}').format(mergeWithFid))
|
||||
|
||||
start = start + add
|
||||
@ -207,7 +216,12 @@ class EliminateSelection(QgisAlgorithm):
|
||||
|
||||
# End while
|
||||
if not processLayer.commitChanges():
|
||||
raise GeoAlgorithmExecutionException(self.tr('Could not commit changes'))
|
||||
raise QgsProcessingException(self.tr('Could not commit changes'))
|
||||
|
||||
for feature in featNotEliminated:
|
||||
writer.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -39,14 +39,15 @@ from qgis.core import (QgsRectangle,
|
||||
QgsPoint,
|
||||
QgsLineString,
|
||||
QgsWkbTypes,
|
||||
QgsProcessing,
|
||||
QgsProcessingException,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterExtent,
|
||||
QgsProcessingParameterNumber,
|
||||
QgsProcessingParameterCrs,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsFields)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.parameters import ParameterExtent
|
||||
from processing.core.parameters import ParameterNumber
|
||||
from processing.core.parameters import ParameterCrs
|
||||
from processing.core.outputs import OutputVector
|
||||
from processing.tools import dataobjects
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
@ -73,19 +74,24 @@ class GridLine(QgisAlgorithm):
|
||||
super().__init__()
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.addParameter(ParameterExtent(self.EXTENT,
|
||||
self.tr('Grid extent'), optional=False))
|
||||
self.addParameter(ParameterNumber(self.HSPACING,
|
||||
self.tr('Horizontal spacing'), 0.0, 1000000000.0, default=0.0001))
|
||||
self.addParameter(ParameterNumber(self.VSPACING,
|
||||
self.tr('Vertical spacing'), 0.0, 1000000000.0, default=0.0001))
|
||||
self.addParameter(ParameterNumber(self.HOVERLAY,
|
||||
self.tr('Horizontal overlay'), 0.0, 1000000000.0, default=0.0))
|
||||
self.addParameter(ParameterNumber(self.VOVERLAY,
|
||||
self.tr('Vertical overlay'), 0.0, 1000000000.0, default=0.0))
|
||||
self.addParameter(ParameterCrs(self.CRS, 'Grid CRS', 'EPSG:4326'))
|
||||
self.addParameter(QgsProcessingParameterExtent(self.EXTENT, self.tr('Grid extent')))
|
||||
|
||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Grid'), datatype=[dataobjects.TYPE_VECTOR_LINE]))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.HSPACING,
|
||||
self.tr('Horizontal spacing'), QgsProcessingParameterNumber.Double,
|
||||
0.0001, False, 0, 1000000000.0))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.VSPACING,
|
||||
self.tr('Vertical spacing'), QgsProcessingParameterNumber.Double,
|
||||
0.0001, False, 0, 1000000000.0))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.HOVERLAY,
|
||||
self.tr('Horizontal overlay'), QgsProcessingParameterNumber.Double,
|
||||
0.0, False, 0, 1000000000.0))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.VOVERLAY,
|
||||
self.tr('Vertical overlay'), QgsProcessingParameterNumber.Double,
|
||||
0.0, False, 0, 1000000000.0))
|
||||
|
||||
self.addParameter(QgsProcessingParameterCrs(self.CRS, 'Grid CRS', 'ProjectCrs'))
|
||||
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Grid'), type=QgsProcessing.TypeVectorLine))
|
||||
|
||||
def name(self):
|
||||
return 'creategridlines'
|
||||
@ -94,33 +100,31 @@ class GridLine(QgisAlgorithm):
|
||||
return self.tr('Create grid (lines)')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
extent = self.getParameterValue(self.EXTENT).split(',')
|
||||
hSpacing = self.getParameterValue(self.HSPACING)
|
||||
vSpacing = self.getParameterValue(self.VSPACING)
|
||||
hOverlay = self.getParameterValue(self.HOVERLAY)
|
||||
vOverlay = self.getParameterValue(self.VOVERLAY)
|
||||
crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.CRS))
|
||||
hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
|
||||
vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
|
||||
hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
|
||||
vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)
|
||||
|
||||
bbox = QgsRectangle(float(extent[0]), float(extent[2]),
|
||||
float(extent[1]), float(extent[3]))
|
||||
bbox = self.parameterAsExtent(parameters, self.EXTENT, context)
|
||||
crs = self.parameterAsCrs(parameters, self.CRS, context)
|
||||
|
||||
width = bbox.width()
|
||||
height = bbox.height()
|
||||
|
||||
if hSpacing <= 0 or vSpacing <= 0:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
raise QgsProcessingException(
|
||||
self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))
|
||||
|
||||
if hSpacing <= hOverlay or vSpacing <= vOverlay:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
raise QgsProcessingException(
|
||||
self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))
|
||||
|
||||
if width < hSpacing:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
raise QgsProcessingException(
|
||||
self.tr('Horizontal spacing is too small for the covered area'))
|
||||
|
||||
if height < vSpacing:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
raise QgsProcessingException(
|
||||
self.tr('Vertical spacing is too small for the covered area'))
|
||||
|
||||
fields = QgsFields()
|
||||
@ -131,7 +135,8 @@ class GridLine(QgisAlgorithm):
|
||||
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
|
||||
fields.append(QgsField('coord', QVariant.Double, '', 24, 15))
|
||||
|
||||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.LineString, crs, context)
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.LineString, crs)
|
||||
|
||||
if hOverlay > 0:
|
||||
hSpace = [hSpacing - hOverlay, hOverlay]
|
||||
@ -154,6 +159,9 @@ class GridLine(QgisAlgorithm):
|
||||
count_update = count_max * 0.10
|
||||
y = bbox.yMaximum()
|
||||
while y >= bbox.yMinimum():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
pt1 = QgsPoint(bbox.xMinimum(), y)
|
||||
pt2 = QgsPoint(bbox.xMaximum(), y)
|
||||
line = QgsLineString()
|
||||
@ -165,7 +173,7 @@ class GridLine(QgisAlgorithm):
|
||||
y,
|
||||
id,
|
||||
y])
|
||||
writer.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
y = y - vSpace[count % 2]
|
||||
id += 1
|
||||
count += 1
|
||||
@ -181,6 +189,9 @@ class GridLine(QgisAlgorithm):
|
||||
count_update = count_max * 0.10
|
||||
x = bbox.xMinimum()
|
||||
while x <= bbox.xMaximum():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
pt1 = QgsPoint(x, bbox.yMaximum())
|
||||
pt2 = QgsPoint(x, bbox.yMinimum())
|
||||
line = QgsLineString()
|
||||
@ -192,11 +203,11 @@ class GridLine(QgisAlgorithm):
|
||||
bbox.yMinimum(),
|
||||
id,
|
||||
x])
|
||||
writer.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
x = x + hSpace[count % 2]
|
||||
id += 1
|
||||
count += 1
|
||||
if int(math.fmod(count, count_update)) == 0:
|
||||
feedback.setProgress(50 + int(count / count_max * 50))
|
||||
|
||||
del writer
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -31,36 +31,29 @@ from qgis.core import (QgsGeometry,
|
||||
QgsPointXY,
|
||||
QgsWkbTypes,
|
||||
QgsApplication,
|
||||
QgsMessageLog,
|
||||
QgsProcessingUtils)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterNumber
|
||||
from processing.core.outputs import OutputVector
|
||||
QgsProcessingException,
|
||||
QgsProcessingParameterNumber)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
|
||||
|
||||
|
||||
class Gridify(QgisAlgorithm):
|
||||
INPUT = 'INPUT'
|
||||
class Gridify(QgisFeatureBasedAlgorithm):
|
||||
|
||||
HSPACING = 'HSPACING'
|
||||
VSPACING = 'VSPACING'
|
||||
OUTPUT = 'OUTPUT'
|
||||
|
||||
def group(self):
|
||||
return self.tr('Vector general tools')
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.h_spacing = None
|
||||
self.v_spacing = None
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.addParameter(ParameterVector(self.INPUT,
|
||||
self.tr('Input Layer')))
|
||||
self.addParameter(ParameterNumber(self.HSPACING,
|
||||
self.tr('Horizontal spacing'), default=0.1))
|
||||
self.addParameter(ParameterNumber(self.VSPACING,
|
||||
self.tr('Vertical spacing'), default=0.1))
|
||||
|
||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Snapped')))
|
||||
def initParameters(self, config=None):
|
||||
self.addParameter(QgsProcessingParameterNumber(self.HSPACING,
|
||||
self.tr('Horizontal spacing'), type=QgsProcessingParameterNumber.Double, minValue=0.0, defaultValue=0.1))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.VSPACING,
|
||||
self.tr('Vertical spacing'), type=QgsProcessingParameterNumber.Double, minValue=0.0, defaultValue=0.1))
|
||||
|
||||
def name(self):
|
||||
return 'snappointstogrid'
|
||||
@ -68,46 +61,45 @@ class Gridify(QgisAlgorithm):
|
||||
def displayName(self):
|
||||
return self.tr('Snap points to grid')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
|
||||
hSpacing = self.getParameterValue(self.HSPACING)
|
||||
vSpacing = self.getParameterValue(self.VSPACING)
|
||||
def outputName(self):
|
||||
return self.tr('Snapped')
|
||||
|
||||
if hSpacing <= 0 or vSpacing <= 0:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.h_spacing = self.parameterAsDouble(parameters, self.HSPACING, context)
|
||||
self.v_spacing = self.parameterAsDouble(parameters, self.VSPACING, context)
|
||||
if self.h_spacing <= 0 or self.v_spacing <= 0:
|
||||
raise QgsProcessingException(
|
||||
self.tr('Invalid grid spacing: {0}/{1}').format(self.h_spacing, self.v_spacing))
|
||||
|
||||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(layer.fields(), layer.wkbType(), layer.crs(),
|
||||
context)
|
||||
return True
|
||||
|
||||
features = QgsProcessingUtils.getFeatures(layer, context)
|
||||
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
|
||||
|
||||
for current, f in enumerate(features):
|
||||
geom = f.geometry()
|
||||
geomType = geom.wkbType()
|
||||
def processFeature(self, feature, feedback):
|
||||
if feature.hasGeometry():
|
||||
geom = feature.geometry()
|
||||
geomType = QgsWkbTypes.flatType(geom.wkbType())
|
||||
newGeom = None
|
||||
|
||||
if geomType == QgsWkbTypes.Point:
|
||||
points = self._gridify([geom.asPoint()], hSpacing, vSpacing)
|
||||
points = self._gridify([geom.asPoint()], self.h_spacing, self.v_spacing)
|
||||
newGeom = QgsGeometry.fromPoint(points[0])
|
||||
elif geomType == QgsWkbTypes.MultiPoint:
|
||||
points = self._gridify(geom.aMultiPoint(), hSpacing, vSpacing)
|
||||
points = self._gridify(geom.asMultiPoint(), self.h_spacing, self.v_spacing)
|
||||
newGeom = QgsGeometry.fromMultiPoint(points)
|
||||
elif geomType == QgsWkbTypes.LineString:
|
||||
points = self._gridify(geom.asPolyline(), hSpacing, vSpacing)
|
||||
points = self._gridify(geom.asPolyline(), self.h_spacing, self.v_spacing)
|
||||
if len(points) < 2:
|
||||
QgsMessageLog.logMessage(self.tr('Failed to gridify feature with FID {0}').format(f.id()), self.tr('Processing'), QgsMessageLog.INFO)
|
||||
feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
|
||||
newGeom = None
|
||||
else:
|
||||
newGeom = QgsGeometry.fromPolyline(points)
|
||||
elif geomType == QgsWkbTypes.MultiLineString:
|
||||
polyline = []
|
||||
for line in geom.asMultiPolyline():
|
||||
points = self._gridify(line, hSpacing, vSpacing)
|
||||
points = self._gridify(line, self.h_spacing, self.v_spacing)
|
||||
if len(points) > 1:
|
||||
polyline.append(points)
|
||||
if len(polyline) <= 0:
|
||||
QgsMessageLog.logMessage(self.tr('Failed to gridify feature with FID {0}').format(f.id()), self.tr('Processing'), QgsMessageLog.INFO)
|
||||
feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
|
||||
newGeom = None
|
||||
else:
|
||||
newGeom = QgsGeometry.fromMultiPolyline(polyline)
|
||||
@ -115,11 +107,11 @@ class Gridify(QgisAlgorithm):
|
||||
elif geomType == QgsWkbTypes.Polygon:
|
||||
polygon = []
|
||||
for line in geom.asPolygon():
|
||||
points = self._gridify(line, hSpacing, vSpacing)
|
||||
points = self._gridify(line, self.h_spacing, self.v_spacing)
|
||||
if len(points) > 1:
|
||||
polygon.append(points)
|
||||
if len(polygon) <= 0:
|
||||
QgsMessageLog.logMessage(self.tr('Failed to gridify feature with FID {0}').format(f.id()), self.tr('Processing'), QgsMessageLog.INFO)
|
||||
feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
|
||||
newGeom = None
|
||||
else:
|
||||
newGeom = QgsGeometry.fromPolygon(polygon)
|
||||
@ -128,7 +120,7 @@ class Gridify(QgisAlgorithm):
|
||||
for polygon in geom.asMultiPolygon():
|
||||
newPolygon = []
|
||||
for line in polygon:
|
||||
points = self._gridify(line, hSpacing, vSpacing)
|
||||
points = self._gridify(line, self.h_spacing, self.v_spacing)
|
||||
if len(points) > 2:
|
||||
newPolygon.append(points)
|
||||
|
||||
@ -136,20 +128,16 @@ class Gridify(QgisAlgorithm):
|
||||
multipolygon.append(newPolygon)
|
||||
|
||||
if len(multipolygon) <= 0:
|
||||
QgsMessageLog.logMessage(self.tr('Failed to gridify feature with FID {0}').format(f.id()), self.tr('Processing'), QgsMessageLog.INFO)
|
||||
feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
|
||||
newGeom = None
|
||||
else:
|
||||
newGeom = QgsGeometry.fromMultiPolygon(multipolygon)
|
||||
|
||||
if newGeom is not None:
|
||||
feat = QgsFeature()
|
||||
feat.setGeometry(newGeom)
|
||||
feat.setAttributes(f.attributes())
|
||||
writer.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
del writer
|
||||
feature.setGeometry(newGeom)
|
||||
else:
|
||||
feature.clearGeometry()
|
||||
return feature
|
||||
|
||||
def _gridify(self, points, hSpacing, vSpacing):
|
||||
nPoints = []
|
||||
|
@ -34,33 +34,33 @@ from qgis.core import (QgsField,
|
||||
QgsFeatureSink,
|
||||
QgsFeatureRequest,
|
||||
QgsWkbTypes,
|
||||
QgsApplication,
|
||||
QgsProject,
|
||||
QgsProcessingUtils)
|
||||
QgsUnitTypes,
|
||||
QgsProcessing,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingException,
|
||||
QgsSpatialIndex)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterTableField
|
||||
from processing.core.parameters import ParameterSelection
|
||||
from processing.core.outputs import OutputVector
|
||||
|
||||
from processing.tools import dataobjects
|
||||
|
||||
from math import sqrt
|
||||
|
||||
|
||||
class HubDistanceLines(QgisAlgorithm):
|
||||
POINTS = 'POINTS'
|
||||
INPUT = 'INPUT'
|
||||
HUBS = 'HUBS'
|
||||
FIELD = 'FIELD'
|
||||
UNIT = 'UNIT'
|
||||
OUTPUT = 'OUTPUT'
|
||||
|
||||
UNITS = ['Meters',
|
||||
'Feet',
|
||||
'Miles',
|
||||
'Kilometers',
|
||||
'Layer units'
|
||||
LAYER_UNITS = 'LAYER_UNITS'
|
||||
|
||||
UNITS = [QgsUnitTypes.DistanceMeters,
|
||||
QgsUnitTypes.DistanceFeet,
|
||||
QgsUnitTypes.DistanceMiles,
|
||||
QgsUnitTypes.DistanceKilometers,
|
||||
LAYER_UNITS
|
||||
]
|
||||
|
||||
def group(self):
|
||||
@ -76,16 +76,16 @@ class HubDistanceLines(QgisAlgorithm):
|
||||
self.tr('Kilometers'),
|
||||
self.tr('Layer units')]
|
||||
|
||||
self.addParameter(ParameterVector(self.POINTS,
|
||||
self.tr('Source points layer')))
|
||||
self.addParameter(ParameterVector(self.HUBS,
|
||||
self.tr('Destination hubs layer')))
|
||||
self.addParameter(ParameterTableField(self.FIELD,
|
||||
self.tr('Hub layer name attribute'), self.HUBS))
|
||||
self.addParameter(ParameterSelection(self.UNIT,
|
||||
self.tr('Measurement unit'), self.units))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
|
||||
self.tr('Source points layer')))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.HUBS,
|
||||
self.tr('Destination hubs layer')))
|
||||
self.addParameter(QgsProcessingParameterField(self.FIELD,
|
||||
self.tr('Hub layer name attribute'), parentLayerParameterName=self.HUBS))
|
||||
self.addParameter(QgsProcessingParameterEnum(self.UNIT,
|
||||
self.tr('Measurement unit'), self.units))
|
||||
|
||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Hub distance'), datatype=[dataobjects.TYPE_VECTOR_LINE]))
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Hub distance'), QgsProcessing.TypeVectorLine))
|
||||
|
||||
def name(self):
|
||||
return 'distancetonearesthublinetohub'
|
||||
@ -94,61 +94,61 @@ class HubDistanceLines(QgisAlgorithm):
|
||||
return self.tr('Distance to nearest hub (line to hub)')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layerPoints = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.POINTS), context)
|
||||
layerHubs = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.HUBS), context)
|
||||
fieldName = self.getParameterValue(self.FIELD)
|
||||
|
||||
units = self.UNITS[self.getParameterValue(self.UNIT)]
|
||||
|
||||
if layerPoints.source() == layerHubs.source():
|
||||
raise GeoAlgorithmExecutionException(
|
||||
if parameters[self.INPUT] == parameters[self.HUBS]:
|
||||
raise QgsProcessingException(
|
||||
self.tr('Same layer given for both hubs and spokes'))
|
||||
|
||||
fields = layerPoints.fields()
|
||||
point_source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
hub_source = self.parameterAsSource(parameters, self.HUBS, context)
|
||||
fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
|
||||
units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT, context)]
|
||||
|
||||
fields = point_source.fields()
|
||||
fields.append(QgsField('HubName', QVariant.String))
|
||||
fields.append(QgsField('HubDist', QVariant.Double))
|
||||
|
||||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.LineString, layerPoints.crs(),
|
||||
context)
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.LineString, point_source.sourceCrs())
|
||||
|
||||
index = QgsProcessingUtils.createSpatialIndex(layerHubs, context)
|
||||
index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs())))
|
||||
|
||||
distance = QgsDistanceArea()
|
||||
distance.setSourceCrs(layerPoints.crs())
|
||||
distance.setSourceCrs(point_source.sourceCrs())
|
||||
distance.setEllipsoid(context.project().ellipsoid())
|
||||
|
||||
# Scan source points, find nearest hub, and write to output file
|
||||
features = QgsProcessingUtils.getFeatures(layerPoints, context)
|
||||
total = 100.0 / layerPoints.featureCount() if layerPoints.featureCount() else 0
|
||||
features = point_source.getFeatures()
|
||||
total = 100.0 / point_source.featureCount() if point_source.featureCount() else 0
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if not f.hasGeometry():
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
continue
|
||||
src = f.geometry().boundingBox().center()
|
||||
|
||||
neighbors = index.nearestNeighbor(src, 1)
|
||||
ft = next(layerHubs.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], layerHubs.fields())))
|
||||
ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs())))
|
||||
closest = ft.geometry().boundingBox().center()
|
||||
hubDist = distance.measureLine(src, closest)
|
||||
|
||||
if units != self.LAYER_UNITS:
|
||||
hub_dist_in_desired_units = distance.convertLengthMeasurement(hubDist, units)
|
||||
else:
|
||||
hub_dist_in_desired_units = hubDist
|
||||
|
||||
attributes = f.attributes()
|
||||
attributes.append(ft[fieldName])
|
||||
if units == 'Feet':
|
||||
attributes.append(hubDist * 3.2808399)
|
||||
elif units == 'Miles':
|
||||
attributes.append(hubDist * 0.000621371192)
|
||||
elif units == 'Kilometers':
|
||||
attributes.append(hubDist / 1000.0)
|
||||
elif units != 'Meters':
|
||||
attributes.append(sqrt(
|
||||
pow(src.x() - closest.x(), 2.0) +
|
||||
pow(src.y() - closest.y(), 2.0)))
|
||||
else:
|
||||
attributes.append(hubDist)
|
||||
attributes.append(hub_dist_in_desired_units)
|
||||
|
||||
feat = QgsFeature()
|
||||
feat.setAttributes(attributes)
|
||||
|
||||
feat.setGeometry(QgsGeometry.fromPolyline([src, closest]))
|
||||
|
||||
writer.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
del writer
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -33,34 +33,31 @@ from qgis.core import (QgsField,
|
||||
QgsDistanceArea,
|
||||
QgsFeature,
|
||||
QgsFeatureRequest,
|
||||
QgsSpatialIndex,
|
||||
QgsWkbTypes,
|
||||
QgsApplication,
|
||||
QgsProject,
|
||||
QgsProcessingUtils)
|
||||
QgsUnitTypes,
|
||||
QgsProcessing,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingException)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterTableField
|
||||
from processing.core.parameters import ParameterSelection
|
||||
from processing.core.outputs import OutputVector
|
||||
|
||||
from processing.tools import dataobjects
|
||||
|
||||
from math import sqrt
|
||||
|
||||
|
||||
class HubDistancePoints(QgisAlgorithm):
|
||||
POINTS = 'POINTS'
|
||||
INPUT = 'INPUT'
|
||||
HUBS = 'HUBS'
|
||||
FIELD = 'FIELD'
|
||||
UNIT = 'UNIT'
|
||||
OUTPUT = 'OUTPUT'
|
||||
LAYER_UNITS = 'LAYER_UNITS'
|
||||
|
||||
UNITS = ['Meters',
|
||||
'Feet',
|
||||
'Miles',
|
||||
'Kilometers',
|
||||
'Layer units'
|
||||
UNITS = [QgsUnitTypes.DistanceMeters,
|
||||
QgsUnitTypes.DistanceFeet,
|
||||
QgsUnitTypes.DistanceMiles,
|
||||
QgsUnitTypes.DistanceKilometers,
|
||||
LAYER_UNITS
|
||||
]
|
||||
|
||||
def group(self):
|
||||
@ -76,16 +73,16 @@ class HubDistancePoints(QgisAlgorithm):
|
||||
self.tr('Kilometers'),
|
||||
self.tr('Layer units')]
|
||||
|
||||
self.addParameter(ParameterVector(self.POINTS,
|
||||
self.tr('Source points layer')))
|
||||
self.addParameter(ParameterVector(self.HUBS,
|
||||
self.tr('Destination hubs layer')))
|
||||
self.addParameter(ParameterTableField(self.FIELD,
|
||||
self.tr('Hub layer name attribute'), self.HUBS))
|
||||
self.addParameter(ParameterSelection(self.UNIT,
|
||||
self.tr('Measurement unit'), self.units))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
|
||||
self.tr('Source points layer')))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.HUBS,
|
||||
self.tr('Destination hubs layer')))
|
||||
self.addParameter(QgsProcessingParameterField(self.FIELD,
|
||||
self.tr('Hub layer name attribute'), parentLayerParameterName=self.HUBS))
|
||||
self.addParameter(QgsProcessingParameterEnum(self.UNIT,
|
||||
self.tr('Measurement unit'), self.units))
|
||||
|
||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Hub distance'), datatype=[dataobjects.TYPE_VECTOR_POINT]))
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Hub distance'), QgsProcessing.TypeVectorPoint))
|
||||
|
||||
def name(self):
|
||||
return 'distancetonearesthubpoints'
|
||||
@ -94,61 +91,62 @@ class HubDistancePoints(QgisAlgorithm):
|
||||
return self.tr('Distance to nearest hub (points)')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layerPoints = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.POINTS), context)
|
||||
layerHubs = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.HUBS), context)
|
||||
fieldName = self.getParameterValue(self.FIELD)
|
||||
|
||||
units = self.UNITS[self.getParameterValue(self.UNIT)]
|
||||
|
||||
if layerPoints.source() == layerHubs.source():
|
||||
raise GeoAlgorithmExecutionException(
|
||||
if parameters[self.INPUT] == parameters[self.HUBS]:
|
||||
raise QgsProcessingException(
|
||||
self.tr('Same layer given for both hubs and spokes'))
|
||||
|
||||
fields = layerPoints.fields()
|
||||
point_source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
hub_source = self.parameterAsSource(parameters, self.HUBS, context)
|
||||
fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
|
||||
units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT, context)]
|
||||
|
||||
fields = point_source.fields()
|
||||
fields.append(QgsField('HubName', QVariant.String))
|
||||
fields.append(QgsField('HubDist', QVariant.Double))
|
||||
|
||||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Point, layerPoints.crs(),
|
||||
context)
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Point, point_source.sourceCrs())
|
||||
|
||||
index = QgsProcessingUtils.createSpatialIndex(layerHubs, context)
|
||||
index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs())))
|
||||
|
||||
distance = QgsDistanceArea()
|
||||
distance.setSourceCrs(layerPoints.crs())
|
||||
distance.setSourceCrs(point_source.sourceCrs())
|
||||
distance.setEllipsoid(context.project().ellipsoid())
|
||||
|
||||
# Scan source points, find nearest hub, and write to output file
|
||||
features = QgsProcessingUtils.getFeatures(layerPoints, context)
|
||||
total = 100.0 / layerPoints.featureCount() if layerPoints.featureCount() else 0
|
||||
features = point_source.getFeatures()
|
||||
total = 100.0 / point_source.featureCount() if point_source.featureCount() else 0
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if not f.hasGeometry():
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
continue
|
||||
|
||||
src = f.geometry().boundingBox().center()
|
||||
|
||||
neighbors = index.nearestNeighbor(src, 1)
|
||||
ft = next(layerHubs.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], layerHubs.fields())))
|
||||
ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs())))
|
||||
closest = ft.geometry().boundingBox().center()
|
||||
hubDist = distance.measureLine(src, closest)
|
||||
|
||||
if units != self.LAYER_UNITS:
|
||||
hub_dist_in_desired_units = distance.convertLengthMeasurement(hubDist, units)
|
||||
else:
|
||||
hub_dist_in_desired_units = hubDist
|
||||
|
||||
attributes = f.attributes()
|
||||
attributes.append(ft[fieldName])
|
||||
if units == 'Feet':
|
||||
attributes.append(hubDist * 3.2808399)
|
||||
elif units == 'Miles':
|
||||
attributes.append(hubDist * 0.000621371192)
|
||||
elif units == 'Kilometers':
|
||||
attributes.append(hubDist / 1000.0)
|
||||
elif units != 'Meters':
|
||||
attributes.append(sqrt(
|
||||
pow(src.x() - closest.x(), 2.0) +
|
||||
pow(src.y() - closest.y(), 2.0)))
|
||||
else:
|
||||
attributes.append(hubDist)
|
||||
attributes.append(hub_dist_in_desired_units)
|
||||
|
||||
feat = QgsFeature()
|
||||
feat.setAttributes(attributes)
|
||||
|
||||
feat.setGeometry(QgsGeometry.fromPoint(src))
|
||||
|
||||
writer.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
del writer
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -31,15 +31,15 @@ from qgis.core import (QgsFeature,
|
||||
QgsGeometry,
|
||||
QgsPointXY,
|
||||
QgsWkbTypes,
|
||||
QgsApplication,
|
||||
QgsProcessingUtils)
|
||||
QgsFeatureRequest,
|
||||
QgsProcessing,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingException,
|
||||
QgsExpression)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterTableField
|
||||
from processing.core.outputs import OutputVector
|
||||
|
||||
from processing.tools import dataobjects
|
||||
from processing.tools import vector
|
||||
|
||||
|
||||
class HubLines(QgisAlgorithm):
|
||||
@ -55,17 +55,21 @@ class HubLines(QgisAlgorithm):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.addParameter(ParameterVector(self.HUBS,
|
||||
self.tr('Hub layer')))
|
||||
self.addParameter(ParameterTableField(self.HUB_FIELD,
|
||||
self.tr('Hub ID field'), self.HUBS))
|
||||
self.addParameter(ParameterVector(self.SPOKES,
|
||||
self.tr('Spoke layer')))
|
||||
self.addParameter(ParameterTableField(self.SPOKE_FIELD,
|
||||
self.tr('Spoke ID field'), self.SPOKES))
|
||||
def tags(self):
|
||||
return self.tr('join,points,lines,connect,hub,spoke').split(',')
|
||||
|
||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Hub lines'), datatype=[dataobjects.TYPE_VECTOR_LINE]))
|
||||
def initAlgorithm(self, config=None):
|
||||
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.HUBS,
|
||||
self.tr('Hub layer')))
|
||||
self.addParameter(QgsProcessingParameterField(self.HUB_FIELD,
|
||||
self.tr('Hub ID field'), parentLayerParameterName=self.HUBS))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.SPOKES,
|
||||
self.tr('Spoke layer')))
|
||||
self.addParameter(QgsProcessingParameterField(self.SPOKE_FIELD,
|
||||
self.tr('Spoke ID field'), parentLayerParameterName=self.SPOKES))
|
||||
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Hub lines'), QgsProcessing.TypeVectorLine))
|
||||
|
||||
def name(self):
|
||||
return 'hublines'
|
||||
@ -74,44 +78,61 @@ class HubLines(QgisAlgorithm):
|
||||
return self.tr('Hub lines')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layerHub = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.HUBS), context)
|
||||
layerSpoke = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.SPOKES), context)
|
||||
|
||||
fieldHub = self.getParameterValue(self.HUB_FIELD)
|
||||
fieldSpoke = self.getParameterValue(self.SPOKE_FIELD)
|
||||
|
||||
if layerHub.source() == layerSpoke.source():
|
||||
raise GeoAlgorithmExecutionException(
|
||||
if parameters[self.SPOKES] == parameters[self.HUBS]:
|
||||
raise QgsProcessingException(
|
||||
self.tr('Same layer given for both hubs and spokes'))
|
||||
|
||||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(layerSpoke.fields(), QgsWkbTypes.LineString,
|
||||
layerSpoke.crs(), context)
|
||||
hub_source = self.parameterAsSource(parameters, self.HUBS, context)
|
||||
spoke_source = self.parameterAsSource(parameters, self.SPOKES, context)
|
||||
field_hub = self.parameterAsString(parameters, self.HUB_FIELD, context)
|
||||
field_hub_index = hub_source.fields().lookupField(field_hub)
|
||||
field_spoke = self.parameterAsString(parameters, self.SPOKE_FIELD, context)
|
||||
field_spoke_index = hub_source.fields().lookupField(field_spoke)
|
||||
|
||||
spokes = QgsProcessingUtils.getFeatures(layerSpoke, context)
|
||||
hubs = QgsProcessingUtils.getFeatures(layerHub, context)
|
||||
total = 100.0 / layerSpoke.featureCount() if layerSpoke.featureCount() else 0
|
||||
fields = vector.combineFields(hub_source.fields(), spoke_source.fields())
|
||||
|
||||
for current, spokepoint in enumerate(spokes):
|
||||
p = spokepoint.geometry().boundingBox().center()
|
||||
spokeX = p.x()
|
||||
spokeY = p.y()
|
||||
spokeId = str(spokepoint[fieldSpoke])
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.LineString, hub_source.sourceCrs())
|
||||
|
||||
for hubpoint in hubs:
|
||||
hubId = str(hubpoint[fieldHub])
|
||||
if hubId == spokeId:
|
||||
p = hubpoint.geometry().boundingBox().center()
|
||||
hubX = p.x()
|
||||
hubY = p.y()
|
||||
hubs = hub_source.getFeatures()
|
||||
total = 100.0 / hub_source.featureCount() if hub_source.featureCount() else 0
|
||||
|
||||
matching_field_types = hub_source.fields().at(field_hub_index).type() == spoke_source.fields().at(field_spoke_index).type()
|
||||
|
||||
for current, hub_point in enumerate(hubs):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if not hub_point.hasGeometry():
|
||||
continue
|
||||
|
||||
p = hub_point.geometry().boundingBox().center()
|
||||
hub_x = p.x()
|
||||
hub_y = p.y()
|
||||
hub_id = str(hub_point[field_hub])
|
||||
hub_attributes = hub_point.attributes()
|
||||
|
||||
request = QgsFeatureRequest().setDestinationCrs(hub_source.sourceCrs())
|
||||
if matching_field_types:
|
||||
request.setFilterExpression(QgsExpression.createFieldEqualityExpression(field_spoke, hub_attributes[field_hub_index]))
|
||||
|
||||
spokes = spoke_source.getFeatures()
|
||||
for spoke_point in spokes:
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
spoke_id = str(spoke_point[field_spoke])
|
||||
if hub_id == spoke_id:
|
||||
p = spoke_point.geometry().boundingBox().center()
|
||||
spoke_x = p.x()
|
||||
spoke_y = p.y()
|
||||
|
||||
f = QgsFeature()
|
||||
f.setAttributes(spokepoint.attributes())
|
||||
f.setAttributes(hub_attributes + spoke_point.attributes())
|
||||
f.setGeometry(QgsGeometry.fromPolyline(
|
||||
[QgsPointXY(spokeX, spokeY), QgsPointXY(hubX, hubY)]))
|
||||
writer.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
|
||||
break
|
||||
[QgsPointXY(hub_x, hub_y), QgsPointXY(spoke_x, spoke_y)]))
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
del writer
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -30,14 +30,13 @@ import os
|
||||
|
||||
from qgis.core import (QgsFeature,
|
||||
QgsFeatureSink,
|
||||
QgsApplication,
|
||||
QgsProcessingUtils)
|
||||
QgsFeatureRequest,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingParameterFeatureSink)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterTable
|
||||
from processing.core.parameters import ParameterTableField
|
||||
from processing.core.outputs import OutputVector
|
||||
from processing.tools import vector
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
@ -45,11 +44,11 @@ pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
class JoinAttributes(QgisAlgorithm):
|
||||
|
||||
OUTPUT_LAYER = 'OUTPUT_LAYER'
|
||||
INPUT_LAYER = 'INPUT_LAYER'
|
||||
INPUT_LAYER_2 = 'INPUT_LAYER_2'
|
||||
TABLE_FIELD = 'TABLE_FIELD'
|
||||
TABLE_FIELD_2 = 'TABLE_FIELD_2'
|
||||
OUTPUT = 'OUTPUT'
|
||||
INPUT = 'INPUT'
|
||||
INPUT_2 = 'INPUT_2'
|
||||
FIELD = 'FIELD'
|
||||
FIELD_2 = 'FIELD_2'
|
||||
|
||||
def group(self):
|
||||
return self.tr('Vector general tools')
|
||||
@ -58,16 +57,15 @@ class JoinAttributes(QgisAlgorithm):
|
||||
super().__init__()
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.addParameter(ParameterVector(self.INPUT_LAYER,
|
||||
self.tr('Input layer')))
|
||||
self.addParameter(ParameterTable(self.INPUT_LAYER_2,
|
||||
self.tr('Input layer 2'), False))
|
||||
self.addParameter(ParameterTableField(self.TABLE_FIELD,
|
||||
self.tr('Table field'), self.INPUT_LAYER))
|
||||
self.addParameter(ParameterTableField(self.TABLE_FIELD_2,
|
||||
self.tr('Table field 2'), self.INPUT_LAYER_2))
|
||||
self.addOutput(OutputVector(self.OUTPUT_LAYER,
|
||||
self.tr('Joined layer')))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
|
||||
self.tr('Input layer')))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT_2,
|
||||
self.tr('Input layer 2')))
|
||||
self.addParameter(QgsProcessingParameterField(self.FIELD,
|
||||
self.tr('Table field'), parentLayerParameterName=self.INPUT))
|
||||
self.addParameter(QgsProcessingParameterField(self.FIELD_2,
|
||||
self.tr('Table field 2'), parentLayerParameterName=self.INPUT_2))
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Joined layer')))
|
||||
|
||||
def name(self):
|
||||
return 'joinattributestable'
|
||||
@ -76,26 +74,27 @@ class JoinAttributes(QgisAlgorithm):
|
||||
return self.tr('Join attributes table')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
input = self.getParameterValue(self.INPUT_LAYER)
|
||||
input2 = self.getParameterValue(self.INPUT_LAYER_2)
|
||||
output = self.getOutputFromName(self.OUTPUT_LAYER)
|
||||
field = self.getParameterValue(self.TABLE_FIELD)
|
||||
field2 = self.getParameterValue(self.TABLE_FIELD_2)
|
||||
input = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
input2 = self.parameterAsSource(parameters, self.INPUT_2, context)
|
||||
field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
field2 = self.parameterAsString(parameters, self.FIELD_2, context)
|
||||
|
||||
layer = QgsProcessingUtils.mapLayerFromString(input, context)
|
||||
joinField1Index = layer.fields().lookupField(field)
|
||||
joinField1Index = input.fields().lookupField(field)
|
||||
joinField2Index = input2.fields().lookupField(field2)
|
||||
|
||||
layer2 = QgsProcessingUtils.mapLayerFromString(input2, context)
|
||||
joinField2Index = layer2.fields().lookupField(field2)
|
||||
outFields = vector.combineFields(input.fields(), input2.fields())
|
||||
|
||||
outFields = vector.combineVectorFields(layer, layer2)
|
||||
writer = output.getVectorWriter(outFields, layer.wkbType(), layer.crs(), context)
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
outFields, input.wkbType(), input.sourceCrs())
|
||||
|
||||
# Cache attributes of Layer 2
|
||||
# Cache attributes of input2
|
||||
cache = {}
|
||||
features = QgsProcessingUtils.getFeatures(layer2, context)
|
||||
total = 100.0 / layer2.featureCount() if layer2.featureCount() else 0
|
||||
features = input2.getFeatures(QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry))
|
||||
total = 100.0 / input2.featureCount() if input2.featureCount() else 0
|
||||
for current, feat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
attrs = feat.attributes()
|
||||
joinValue2 = str(attrs[joinField2Index])
|
||||
if joinValue2 not in cache:
|
||||
@ -104,14 +103,18 @@ class JoinAttributes(QgisAlgorithm):
|
||||
|
||||
# Create output vector layer with additional attribute
|
||||
outFeat = QgsFeature()
|
||||
features = QgsProcessingUtils.getFeatures(layer, context)
|
||||
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
|
||||
features = input.getFeatures()
|
||||
total = 100.0 / input.featureCount() if input.featureCount() else 0
|
||||
for current, feat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
outFeat.setGeometry(feat.geometry())
|
||||
attrs = feat.attributes()
|
||||
joinValue1 = str(attrs[joinField1Index])
|
||||
attrs.extend(cache.get(joinValue1, []))
|
||||
outFeat.setAttributes(attrs)
|
||||
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
del writer
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -29,36 +29,34 @@ __revision__ = '$Format:%H$'
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
from qgis.PyQt.QtCore import QVariant
|
||||
from qgis.core import (QgsApplication,
|
||||
QgsFeature,
|
||||
from qgis.core import (QgsFeature,
|
||||
QgsFeatureSink,
|
||||
QgsFields,
|
||||
QgsField,
|
||||
QgsGeometry,
|
||||
QgsDistanceArea,
|
||||
QgsProject,
|
||||
QgsPointXY,
|
||||
QgsLineString,
|
||||
QgsWkbTypes,
|
||||
QgsProcessingUtils)
|
||||
QgsFeatureRequest,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingParameterString,
|
||||
QgsProcessing,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingParameterFolderDestination)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterTableField
|
||||
from processing.core.parameters import ParameterString
|
||||
from processing.core.outputs import OutputVector
|
||||
from processing.core.outputs import OutputDirectory
|
||||
from processing.tools import dataobjects
|
||||
|
||||
|
||||
class PointsToPaths(QgisAlgorithm):
|
||||
|
||||
VECTOR = 'VECTOR'
|
||||
INPUT = 'INPUT'
|
||||
GROUP_FIELD = 'GROUP_FIELD'
|
||||
ORDER_FIELD = 'ORDER_FIELD'
|
||||
DATE_FORMAT = 'DATE_FORMAT'
|
||||
#GAP_PERIOD = 'GAP_PERIOD'
|
||||
OUTPUT_LINES = 'OUTPUT_LINES'
|
||||
OUTPUT_TEXT = 'OUTPUT_TEXT'
|
||||
OUTPUT = 'OUTPUT'
|
||||
OUTPUT_TEXT_DIR = 'OUTPUT_TEXT_DIR'
|
||||
|
||||
def group(self):
|
||||
return self.tr('Vector creation tools')
|
||||
@ -66,20 +64,23 @@ class PointsToPaths(QgisAlgorithm):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def tags(self):
|
||||
return self.tr('join,points,lines,connect').split(',')
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.addParameter(ParameterVector(self.VECTOR,
|
||||
self.tr('Input point layer'), [dataobjects.TYPE_VECTOR_POINT]))
|
||||
self.addParameter(ParameterTableField(self.GROUP_FIELD,
|
||||
self.tr('Group field'), self.VECTOR))
|
||||
self.addParameter(ParameterTableField(self.ORDER_FIELD,
|
||||
self.tr('Order field'), self.VECTOR))
|
||||
self.addParameter(ParameterString(self.DATE_FORMAT,
|
||||
self.tr('Date format (if order field is DateTime)'), '', optional=True))
|
||||
#self.addParameter(ParameterNumber(
|
||||
# self.GAP_PERIOD,
|
||||
# 'Gap period (if order field is DateTime)', 0, 60, 0))
|
||||
self.addOutput(OutputVector(self.OUTPUT_LINES, self.tr('Paths'), datatype=[dataobjects.TYPE_VECTOR_LINE]))
|
||||
self.addOutput(OutputDirectory(self.OUTPUT_TEXT, self.tr('Directory')))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
|
||||
self.tr('Input point layer'), [QgsProcessing.TypeVectorPoint]))
|
||||
self.addParameter(QgsProcessingParameterField(self.ORDER_FIELD,
|
||||
self.tr('Order field'), parentLayerParameterName=self.INPUT))
|
||||
self.addParameter(QgsProcessingParameterField(self.GROUP_FIELD,
|
||||
self.tr('Group field'), parentLayerParameterName=self.INPUT, optional=True))
|
||||
self.addParameter(QgsProcessingParameterString(self.DATE_FORMAT,
|
||||
self.tr('Date format (if order field is DateTime)'), optional=True))
|
||||
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Paths'), QgsProcessing.TypeVectorLine))
|
||||
output_dir_param = QgsProcessingParameterFolderDestination(self.OUTPUT_TEXT_DIR, self.tr('Directory for text output'), optional=True)
|
||||
output_dir_param.setCreateByDefault(False)
|
||||
self.addParameter(output_dir_param)
|
||||
|
||||
def name(self):
|
||||
return 'pointstopath'
|
||||
@ -88,29 +89,58 @@ class PointsToPaths(QgisAlgorithm):
|
||||
return self.tr('Points to path')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.VECTOR), context)
|
||||
groupField = self.getParameterValue(self.GROUP_FIELD)
|
||||
orderField = self.getParameterValue(self.ORDER_FIELD)
|
||||
dateFormat = str(self.getParameterValue(self.DATE_FORMAT))
|
||||
#gap = int(self.getParameterValue(self.GAP_PERIOD))
|
||||
dirName = self.getOutputValue(self.OUTPUT_TEXT)
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
group_field_name = self.parameterAsString(parameters, self.GROUP_FIELD, context)
|
||||
order_field_name = self.parameterAsString(parameters, self.ORDER_FIELD, context)
|
||||
date_format = self.parameterAsString(parameters, self.DATE_FORMAT, context)
|
||||
text_dir = self.parameterAsString(parameters, self.OUTPUT_TEXT_DIR, context)
|
||||
|
||||
group_field_index = source.fields().lookupField(group_field_name)
|
||||
order_field_index = source.fields().lookupField(order_field_name)
|
||||
|
||||
if group_field_index >= 0:
|
||||
group_field_def = source.fields().at(group_field_index)
|
||||
else:
|
||||
group_field_def = None
|
||||
order_field_def = source.fields().at(order_field_index)
|
||||
|
||||
fields = QgsFields()
|
||||
fields.append(QgsField('group', QVariant.String, '', 254, 0))
|
||||
fields.append(QgsField('begin', QVariant.String, '', 254, 0))
|
||||
fields.append(QgsField('end', QVariant.String, '', 254, 0))
|
||||
writer = self.getOutputFromName(self.OUTPUT_LINES).getVectorWriter(fields, QgsWkbTypes.LineString, layer.crs(),
|
||||
context)
|
||||
if group_field_def is not None:
|
||||
fields.append(group_field_def)
|
||||
begin_field = QgsField(order_field_def)
|
||||
begin_field.setName('begin')
|
||||
fields.append(begin_field)
|
||||
end_field = QgsField(order_field_def)
|
||||
end_field.setName('end')
|
||||
fields.append(end_field)
|
||||
|
||||
output_wkb = QgsWkbTypes.LineString
|
||||
if QgsWkbTypes.hasM(source.wkbType()):
|
||||
output_wkb = QgsWkbTypes.addM(output_wkb)
|
||||
if QgsWkbTypes.hasZ(source.wkbType()):
|
||||
output_wkb = QgsWkbTypes.addZ(output_wkb)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, output_wkb, source.sourceCrs())
|
||||
|
||||
points = dict()
|
||||
features = QgsProcessingUtils.getFeatures(layer, context)
|
||||
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
|
||||
features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([group_field_index, order_field_index]))
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
for current, f in enumerate(features):
|
||||
point = f.geometry().asPoint()
|
||||
group = f[groupField]
|
||||
order = f[orderField]
|
||||
if dateFormat != '':
|
||||
order = datetime.strptime(str(order), dateFormat)
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if not f.hasGeometry():
|
||||
continue
|
||||
|
||||
point = f.geometry().geometry().clone()
|
||||
if group_field_index >= 0:
|
||||
group = f.attributes()[group_field_index]
|
||||
else:
|
||||
group = 1
|
||||
order = f.attributes()[order_field_index]
|
||||
if date_format != '':
|
||||
order = datetime.strptime(str(order), date_format)
|
||||
if group in points:
|
||||
points[group].append((order, point))
|
||||
else:
|
||||
@ -121,46 +151,45 @@ class PointsToPaths(QgisAlgorithm):
|
||||
feedback.setProgress(0)
|
||||
|
||||
da = QgsDistanceArea()
|
||||
da.setSourceCrs(layer.sourceCrs())
|
||||
da.setSourceCrs(source.sourceCrs())
|
||||
da.setEllipsoid(context.project().ellipsoid())
|
||||
|
||||
current = 0
|
||||
total = 100.0 / len(points) if points else 1
|
||||
for group, vertices in list(points.items()):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
vertices.sort()
|
||||
f = QgsFeature()
|
||||
f.initAttributes(len(fields))
|
||||
f.setFields(fields)
|
||||
f['group'] = group
|
||||
f['begin'] = vertices[0][0]
|
||||
f['end'] = vertices[-1][0]
|
||||
attributes = []
|
||||
if group_field_index >= 0:
|
||||
attributes.append(group)
|
||||
attributes.extend([vertices[0][0], vertices[-1][0]])
|
||||
f.setAttributes(attributes)
|
||||
line = [node[1] for node in vertices]
|
||||
|
||||
fileName = os.path.join(dirName, '%s.txt' % group)
|
||||
if text_dir:
|
||||
fileName = os.path.join(text_dir, '%s.txt' % group)
|
||||
|
||||
with open(fileName, 'w') as fl:
|
||||
fl.write('angle=Azimuth\n')
|
||||
fl.write('heading=Coordinate_System\n')
|
||||
fl.write('dist_units=Default\n')
|
||||
with open(fileName, 'w') as fl:
|
||||
fl.write('angle=Azimuth\n')
|
||||
fl.write('heading=Coordinate_System\n')
|
||||
fl.write('dist_units=Default\n')
|
||||
|
||||
line = []
|
||||
i = 0
|
||||
for node in vertices:
|
||||
line.append(node[1])
|
||||
for i in range(len(line)):
|
||||
if i == 0:
|
||||
fl.write('startAt=%f;%f;90\n' % (line[i].x(), line[i].y()))
|
||||
fl.write('survey=Polygonal\n')
|
||||
fl.write('[data]\n')
|
||||
else:
|
||||
angle = line[i - 1].azimuth(line[i])
|
||||
distance = da.measureLine(QgsPointXY(line[i - 1]), QgsPointXY(line[i]))
|
||||
fl.write('%f;%f;90\n' % (angle, distance))
|
||||
|
||||
if i == 0:
|
||||
fl.write('startAt=%f;%f;90\n' % (node[1].x(), node[1].y()))
|
||||
fl.write('survey=Polygonal\n')
|
||||
fl.write('[data]\n')
|
||||
else:
|
||||
angle = line[i - 1].azimuth(line[i])
|
||||
distance = da.measureLine(line[i - 1], line[i])
|
||||
fl.write('%f;%f;90\n' % (angle, distance))
|
||||
|
||||
i += 1
|
||||
|
||||
f.setGeometry(QgsGeometry.fromPolyline(line))
|
||||
writer.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
f.setGeometry(QgsGeometry(QgsLineString(line)))
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
current += 1
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
del writer
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -60,6 +60,7 @@ from .DensifyGeometriesInterval import DensifyGeometriesInterval
|
||||
from .Difference import Difference
|
||||
from .DropGeometry import DropGeometry
|
||||
from .DropMZValues import DropMZValues
|
||||
from .EliminateSelection import EliminateSelection
|
||||
from .EquivalentNumField import EquivalentNumField
|
||||
from .Explode import Explode
|
||||
from .ExportGeometryInfo import ExportGeometryInfo
|
||||
@ -70,12 +71,18 @@ from .ExtractSpecificNodes import ExtractSpecificNodes
|
||||
from .FixedDistanceBuffer import FixedDistanceBuffer
|
||||
from .FixGeometry import FixGeometry
|
||||
from .GeometryByExpression import GeometryByExpression
|
||||
from .Gridify import Gridify
|
||||
from .GridLine import GridLine
|
||||
from .GridPolygon import GridPolygon
|
||||
from .Heatmap import Heatmap
|
||||
from .Hillshade import Hillshade
|
||||
from .HubDistanceLines import HubDistanceLines
|
||||
from .HubDistancePoints import HubDistancePoints
|
||||
from .HubLines import HubLines
|
||||
from .ImportIntoPostGIS import ImportIntoPostGIS
|
||||
from .ImportIntoSpatialite import ImportIntoSpatialite
|
||||
from .Intersection import Intersection
|
||||
from .JoinAttributes import JoinAttributes
|
||||
from .LinesIntersection import LinesIntersection
|
||||
from .LinesToPolygons import LinesToPolygons
|
||||
from .MeanCoords import MeanCoords
|
||||
@ -89,6 +96,7 @@ from .PointOnSurface import PointOnSurface
|
||||
from .PointsAlongGeometry import PointsAlongGeometry
|
||||
from .PointsInPolygon import PointsInPolygon
|
||||
from .PointsLayerFromTable import PointsLayerFromTable
|
||||
from .PointsToPaths import PointsToPaths
|
||||
from .PoleOfInaccessibility import PoleOfInaccessibility
|
||||
from .Polygonize import Polygonize
|
||||
from .PolygonsToLines import PolygonsToLines
|
||||
@ -99,6 +107,8 @@ from .RandomPointsAlongLines import RandomPointsAlongLines
|
||||
from .RandomPointsExtent import RandomPointsExtent
|
||||
from .RandomPointsLayer import RandomPointsLayer
|
||||
from .RandomPointsPolygons import RandomPointsPolygons
|
||||
from .RandomSelection import RandomSelection
|
||||
from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
|
||||
from .RasterLayerStatistics import RasterLayerStatistics
|
||||
from .RegularPoints import RegularPoints
|
||||
from .ReverseLineDirection import ReverseLineDirection
|
||||
@ -122,9 +132,11 @@ from .SnapGeometries import SnapGeometriesToLayer
|
||||
from .SpatialiteExecuteSQL import SpatialiteExecuteSQL
|
||||
from .SpatialIndex import SpatialIndex
|
||||
from .SplitWithLines import SplitWithLines
|
||||
from .StatisticsByCategories import StatisticsByCategories
|
||||
from .SumLines import SumLines
|
||||
from .SymmetricalDifference import SymmetricalDifference
|
||||
from .TextToFloat import TextToFloat
|
||||
from .TopoColors import TopoColor
|
||||
from .Translate import Translate
|
||||
from .TruncateTable import TruncateTable
|
||||
from .Union import Union
|
||||
@ -135,24 +147,14 @@ from .VoronoiPolygons import VoronoiPolygons
|
||||
from .ZonalStatistics import ZonalStatistics
|
||||
|
||||
# from .ExtractByLocation import ExtractByLocation
|
||||
# from .RandomSelection import RandomSelection
|
||||
# from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
|
||||
# from .SelectByLocation import SelectByLocation
|
||||
# from .SpatialJoin import SpatialJoin
|
||||
# from .GridLine import GridLine
|
||||
# from .Gridify import Gridify
|
||||
# from .HubDistancePoints import HubDistancePoints
|
||||
# from .HubDistanceLines import HubDistanceLines
|
||||
# from .HubLines import HubLines
|
||||
# from .GeometryConvert import GeometryConvert
|
||||
# from .StatisticsByCategories import StatisticsByCategories
|
||||
# from .FieldsCalculator import FieldsCalculator
|
||||
# from .FieldPyculator import FieldsPyculator
|
||||
# from .JoinAttributes import JoinAttributes
|
||||
# from .PointsDisplacement import PointsDisplacement
|
||||
# from .PointsFromPolygons import PointsFromPolygons
|
||||
# from .PointsFromLines import PointsFromLines
|
||||
# from .PointsToPaths import PointsToPaths
|
||||
# from .SetVectorStyle import SetVectorStyle
|
||||
# from .SetRasterStyle import SetRasterStyle
|
||||
# from .SelectByAttributeSum import SelectByAttributeSum
|
||||
@ -169,8 +171,6 @@ from .ZonalStatistics import ZonalStatistics
|
||||
# from .RasterCalculator import RasterCalculator
|
||||
# from .ExecuteSQL import ExecuteSQL
|
||||
# from .FindProjection import FindProjection
|
||||
# from .TopoColors import TopoColor
|
||||
# from .EliminateSelection import EliminateSelection
|
||||
|
||||
pluginPath = os.path.normpath(os.path.join(
|
||||
os.path.split(os.path.dirname(__file__))[0], os.pardir))
|
||||
@ -185,19 +185,15 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
|
||||
def getAlgs(self):
|
||||
# algs = [
|
||||
# RandomSelection(), RandomSelectionWithinSubsets(),
|
||||
# SelectByLocation(),
|
||||
# ExtractByLocation(),
|
||||
# SpatialJoin(),
|
||||
# GridLine(), Gridify(), HubDistancePoints(),
|
||||
# HubDistanceLines(), HubLines(),
|
||||
# GeometryConvert(), FieldsCalculator(),
|
||||
# JoinAttributes(),
|
||||
# FieldsPyculator(),
|
||||
# StatisticsByCategories(),
|
||||
#
|
||||
# RasterLayerStatistics(), PointsDisplacement(),
|
||||
# PointsFromPolygons(),
|
||||
# PointsFromLines(), PointsToPaths(),
|
||||
# PointsFromLines(),
|
||||
# SetVectorStyle(), SetRasterStyle(),
|
||||
# HypsometricCurves(),
|
||||
# FieldsMapper(), SelectByAttributeSum(), Datasources2Vrt(),
|
||||
@ -209,7 +205,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
# IdwInterpolation(), TinInterpolation(),
|
||||
# RasterCalculator(),
|
||||
# ExecuteSQL(), FindProjection(),
|
||||
# TopoColor(), EliminateSelection()
|
||||
# ]
|
||||
algs = [AddTableField(),
|
||||
Aspect(),
|
||||
@ -231,6 +226,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
Difference(),
|
||||
DropGeometry(),
|
||||
DropMZValues(),
|
||||
EliminateSelection(),
|
||||
EquivalentNumField(),
|
||||
Explode(),
|
||||
ExportGeometryInfo(),
|
||||
@ -241,12 +237,18 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
FixedDistanceBuffer(),
|
||||
FixGeometry(),
|
||||
GeometryByExpression(),
|
||||
Gridify(),
|
||||
GridLine(),
|
||||
GridPolygon(),
|
||||
Heatmap(),
|
||||
Hillshade(),
|
||||
HubDistanceLines(),
|
||||
HubDistancePoints(),
|
||||
HubLines(),
|
||||
ImportIntoPostGIS(),
|
||||
ImportIntoSpatialite(),
|
||||
Intersection(),
|
||||
JoinAttributes(),
|
||||
LinesIntersection(),
|
||||
LinesToPolygons(),
|
||||
MeanCoords(),
|
||||
@ -260,6 +262,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
PointsAlongGeometry(),
|
||||
PointsInPolygon(),
|
||||
PointsLayerFromTable(),
|
||||
PointsToPaths(),
|
||||
PoleOfInaccessibility(),
|
||||
Polygonize(),
|
||||
PolygonsToLines(),
|
||||
@ -270,6 +273,8 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
RandomPointsExtent(),
|
||||
RandomPointsLayer(),
|
||||
RandomPointsPolygons(),
|
||||
RandomSelection(),
|
||||
RandomSelectionWithinSubsets(),
|
||||
RasterLayerStatistics(),
|
||||
RegularPoints(),
|
||||
ReverseLineDirection(),
|
||||
@ -293,9 +298,11 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
SpatialiteExecuteSQL(),
|
||||
SpatialIndex(),
|
||||
SplitWithLines(),
|
||||
StatisticsByCategories(),
|
||||
SumLines(),
|
||||
SymmetricalDifference(),
|
||||
TextToFloat(),
|
||||
TopoColor(),
|
||||
Translate(),
|
||||
TruncateTable(),
|
||||
Union(),
|
||||
|
@ -30,13 +30,16 @@ import os
|
||||
import random
|
||||
|
||||
from qgis.PyQt.QtGui import QIcon
|
||||
from qgis.core import QgsFeatureSink, QgsProcessingUtils
|
||||
from qgis.core import (QgsFeatureSink,
|
||||
QgsProcessingException,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterVectorLayer,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterNumber,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingOutputVectorLayer)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.parameters import ParameterSelection
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterNumber
|
||||
from processing.core.outputs import OutputVector
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
@ -61,13 +64,14 @@ class RandomSelection(QgisAlgorithm):
|
||||
self.methods = [self.tr('Number of selected features'),
|
||||
self.tr('Percentage of selected features')]
|
||||
|
||||
self.addParameter(ParameterVector(self.INPUT,
|
||||
self.tr('Input layer')))
|
||||
self.addParameter(ParameterSelection(self.METHOD,
|
||||
self.tr('Method'), self.methods, 0))
|
||||
self.addParameter(ParameterNumber(self.NUMBER,
|
||||
self.tr('Number/percentage of selected features'), 0, None, 10))
|
||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Selection'), True))
|
||||
self.addParameter(QgsProcessingParameterVectorLayer(self.INPUT,
|
||||
self.tr('Input layer')))
|
||||
self.addParameter(QgsProcessingParameterEnum(self.METHOD,
|
||||
self.tr('Method'), self.methods, False, 0))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.NUMBER,
|
||||
self.tr('Number/percentage of selected features'), QgsProcessingParameterNumber.Integer,
|
||||
10, False, 0.0, 999999999999.0))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Selected (random)')))
|
||||
|
||||
def name(self):
|
||||
return 'randomselection'
|
||||
@ -76,23 +80,20 @@ class RandomSelection(QgisAlgorithm):
|
||||
return self.tr('Random selection')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
filename = self.getParameterValue(self.INPUT)
|
||||
layer = QgsProcessingUtils.mapLayerFromString(filename, context)
|
||||
method = self.getParameterValue(self.METHOD)
|
||||
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
|
||||
featureCount = layer.featureCount()
|
||||
value = int(self.getParameterValue(self.NUMBER))
|
||||
|
||||
layer.removeSelection()
|
||||
value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
|
||||
if method == 0:
|
||||
if value > featureCount:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
raise QgsProcessingException(
|
||||
self.tr('Selected number is greater than feature count. '
|
||||
'Choose a lower value and try again.'))
|
||||
else:
|
||||
if value > 100:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
raise QgsProcessingException(
|
||||
self.tr("Percentage can't be greater than 100. Set a "
|
||||
"different value and try again."))
|
||||
value = int(round(value / 100.0, 4) * featureCount)
|
||||
@ -100,4 +101,4 @@ class RandomSelection(QgisAlgorithm):
|
||||
selran = random.sample(list(range(featureCount)), value)
|
||||
|
||||
layer.selectByIds(selran)
|
||||
self.setOutputValue(self.OUTPUT, filename)
|
||||
return {self.OUTPUT: parameters[self.INPUT]}
|
||||
|
@ -31,15 +31,17 @@ import random
|
||||
|
||||
from qgis.PyQt.QtGui import QIcon
|
||||
|
||||
from qgis.core import QgsFeature, QgsFeatureSink, QgsProcessingUtils
|
||||
|
||||
from qgis.core import (QgsFeatureRequest,
|
||||
QgsProcessingException,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterVectorLayer,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingParameterNumber,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingOutputVectorLayer)
|
||||
from collections import defaultdict
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.parameters import ParameterSelection
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterNumber
|
||||
from processing.core.parameters import ParameterTableField
|
||||
from processing.core.outputs import OutputVector
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
@ -65,16 +67,17 @@ class RandomSelectionWithinSubsets(QgisAlgorithm):
|
||||
self.methods = [self.tr('Number of selected features'),
|
||||
self.tr('Percentage of selected features')]
|
||||
|
||||
self.addParameter(ParameterVector(self.INPUT,
|
||||
self.tr('Input layer')))
|
||||
self.addParameter(ParameterTableField(self.FIELD,
|
||||
self.tr('ID Field'), self.INPUT))
|
||||
self.addParameter(ParameterSelection(self.METHOD,
|
||||
self.tr('Method'), self.methods, 0))
|
||||
self.addParameter(ParameterNumber(self.NUMBER,
|
||||
self.tr('Number/percentage of selected features'), 1, None, 10))
|
||||
|
||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Selection stratified'), True))
|
||||
self.addParameter(QgsProcessingParameterVectorLayer(self.INPUT,
|
||||
self.tr('Input layer')))
|
||||
self.addParameter(QgsProcessingParameterField(self.FIELD,
|
||||
self.tr('ID field'), None, self.INPUT))
|
||||
self.addParameter(QgsProcessingParameterEnum(self.METHOD,
|
||||
self.tr('Method'), self.methods, False, 0))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.NUMBER,
|
||||
self.tr('Number/percentage of selected features'),
|
||||
QgsProcessingParameterNumber.Integer,
|
||||
10, False, 0.0, 999999999999.0))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Selected (stratified random)')))
|
||||
|
||||
def name(self):
|
||||
return 'randomselectionwithinsubsets'
|
||||
@ -83,61 +86,52 @@ class RandomSelectionWithinSubsets(QgisAlgorithm):
|
||||
return self.tr('Random selection within subsets')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
filename = self.getParameterValue(self.INPUT)
|
||||
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
|
||||
layer = QgsProcessingUtils.mapLayerFromString(filename, context)
|
||||
field = self.getParameterValue(self.FIELD)
|
||||
method = self.getParameterValue(self.METHOD)
|
||||
|
||||
layer.removeSelection()
|
||||
index = layer.fields().lookupField(field)
|
||||
|
||||
unique = QgsProcessingUtils.uniqueValues(layer, index, context)
|
||||
unique = layer.uniqueValues(index)
|
||||
featureCount = layer.featureCount()
|
||||
|
||||
value = int(self.getParameterValue(self.NUMBER))
|
||||
value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
if method == 0:
|
||||
if value > featureCount:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
raise QgsProcessingException(
|
||||
self.tr('Selected number is greater that feature count. '
|
||||
'Choose lesser value and try again.'))
|
||||
else:
|
||||
if value > 100:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
raise QgsProcessingException(
|
||||
self.tr("Percentage can't be greater than 100. Set a "
|
||||
"different value and try again."))
|
||||
value = value / 100.0
|
||||
|
||||
selran = []
|
||||
inFeat = QgsFeature()
|
||||
|
||||
current = 0
|
||||
total = 100.0 / (featureCount * len(unique)) if featureCount else 1
|
||||
|
||||
if not len(unique) == featureCount:
|
||||
for i in unique:
|
||||
features = QgsProcessingUtils.getFeatures(layer, context)
|
||||
FIDs = []
|
||||
for inFeat in features:
|
||||
attrs = inFeat.attributes()
|
||||
if attrs[index] == i:
|
||||
FIDs.append(inFeat.id())
|
||||
current += 1
|
||||
feedback.setProgress(int(current * total))
|
||||
classes = defaultdict(list)
|
||||
|
||||
if method == 1:
|
||||
selValue = int(round(value * len(FIDs), 0))
|
||||
else:
|
||||
selValue = value
|
||||
features = layer.getFeatures(QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry).setSubsetOfAttributes([index]))
|
||||
|
||||
if selValue >= len(FIDs):
|
||||
selFeat = FIDs
|
||||
else:
|
||||
selFeat = random.sample(FIDs, selValue)
|
||||
for i, feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
classes[feature.attributes()[index]].append(feature.id())
|
||||
feedback.setProgress(int(i * total))
|
||||
|
||||
selran = []
|
||||
for subset in classes.values():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
selValue = value if method != 1 else int(round(value * len(subset), 0))
|
||||
selran.extend(random.sample(subset, selValue))
|
||||
|
||||
selran.extend(selFeat)
|
||||
layer.selectByIds(selran)
|
||||
else:
|
||||
layer.selectByIds(list(range(featureCount))) # FIXME: implies continuous feature ids
|
||||
|
||||
self.setOutputValue(self.OUTPUT, filename)
|
||||
return {self.OUTPUT: parameters[self.INPUT]}
|
||||
|
@ -26,19 +26,24 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
||||
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
from qgis.core import (QgsApplication,
|
||||
QgsFeatureSink,
|
||||
from qgis.core import (QgsProcessingParameterFeatureSource,
|
||||
QgsStatisticalSummary,
|
||||
QgsProcessingUtils)
|
||||
from processing.core.outputs import OutputTable
|
||||
QgsFeatureRequest,
|
||||
QgsProcessingParameterField,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsFields,
|
||||
QgsField,
|
||||
QgsWkbTypes,
|
||||
QgsCoordinateReferenceSystem,
|
||||
QgsFeature,
|
||||
QgsFeatureSink)
|
||||
from qgis.PyQt.QtCore import QVariant
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterTableField
|
||||
|
||||
|
||||
class StatisticsByCategories(QgisAlgorithm):
|
||||
|
||||
INPUT_LAYER = 'INPUT_LAYER'
|
||||
INPUT = 'INPUT'
|
||||
VALUES_FIELD_NAME = 'VALUES_FIELD_NAME'
|
||||
CATEGORIES_FIELD_NAME = 'CATEGORIES_FIELD_NAME'
|
||||
OUTPUT = 'OUTPUT'
|
||||
@ -50,16 +55,16 @@ class StatisticsByCategories(QgisAlgorithm):
|
||||
super().__init__()
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.addParameter(ParameterVector(self.INPUT_LAYER,
|
||||
self.tr('Input vector layer')))
|
||||
self.addParameter(ParameterTableField(self.VALUES_FIELD_NAME,
|
||||
self.tr('Field to calculate statistics on'),
|
||||
self.INPUT_LAYER, ParameterTableField.DATA_TYPE_NUMBER))
|
||||
self.addParameter(ParameterTableField(self.CATEGORIES_FIELD_NAME,
|
||||
self.tr('Field with categories'),
|
||||
self.INPUT_LAYER, ParameterTableField.DATA_TYPE_ANY))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
|
||||
self.tr('Input vector layer')))
|
||||
self.addParameter(QgsProcessingParameterField(self.VALUES_FIELD_NAME,
|
||||
self.tr('Field to calculate statistics on'),
|
||||
parentLayerParameterName=self.INPUT, type=QgsProcessingParameterField.Numeric))
|
||||
self.addParameter(QgsProcessingParameterField(self.CATEGORIES_FIELD_NAME,
|
||||
self.tr('Field with categories'),
|
||||
parentLayerParameterName=self.INPUT, type=QgsProcessingParameterField.Any))
|
||||
|
||||
self.addOutput(OutputTable(self.OUTPUT, self.tr('Statistics by category')))
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Statistics by category')))
|
||||
|
||||
def name(self):
|
||||
return 'statisticsbycategories'
|
||||
@ -68,36 +73,51 @@ class StatisticsByCategories(QgisAlgorithm):
|
||||
return self.tr('Statistics by categories')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
|
||||
valuesFieldName = self.getParameterValue(self.VALUES_FIELD_NAME)
|
||||
categoriesFieldName = self.getParameterValue(self.CATEGORIES_FIELD_NAME)
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
value_field_name = self.parameterAsString(parameters, self.VALUES_FIELD_NAME, context)
|
||||
category_field_name = self.parameterAsString(parameters, self.CATEGORIES_FIELD_NAME, context)
|
||||
|
||||
output = self.getOutputFromName(self.OUTPUT)
|
||||
valuesField = layer.fields().lookupField(valuesFieldName)
|
||||
categoriesField = layer.fields().lookupField(categoriesFieldName)
|
||||
value_field_index = source.fields().lookupField(value_field_name)
|
||||
category_field_index = source.fields().lookupField(category_field_name)
|
||||
|
||||
features = QgsProcessingUtils.getFeatures(layer, context)
|
||||
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
|
||||
features = source.getFeatures(QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry))
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
values = {}
|
||||
for current, feat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
attrs = feat.attributes()
|
||||
try:
|
||||
value = float(attrs[valuesField])
|
||||
cat = str(attrs[categoriesField])
|
||||
value = float(attrs[value_field_index])
|
||||
cat = attrs[category_field_index]
|
||||
if cat not in values:
|
||||
values[cat] = []
|
||||
values[cat].append(value)
|
||||
except:
|
||||
pass
|
||||
|
||||
fields = ['category', 'min', 'max', 'mean', 'stddev', 'sum', 'count']
|
||||
writer = output.getTableWriter(fields)
|
||||
fields = QgsFields()
|
||||
fields.append(source.fields().at(category_field_index))
|
||||
fields.append(QgsField('min', QVariant.Double))
|
||||
fields.append(QgsField('max', QVariant.Double))
|
||||
fields.append(QgsField('mean', QVariant.Double))
|
||||
fields.append(QgsField('stddev', QVariant.Double))
|
||||
fields.append(QgsField('sum', QVariant.Double))
|
||||
fields.append(QgsField('count', QVariant.Int))
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
|
||||
|
||||
stat = QgsStatisticalSummary(QgsStatisticalSummary.Min | QgsStatisticalSummary.Max |
|
||||
QgsStatisticalSummary.Mean | QgsStatisticalSummary.StDevSample |
|
||||
QgsStatisticalSummary.Sum | QgsStatisticalSummary.Count)
|
||||
|
||||
for (cat, v) in list(values.items()):
|
||||
stat.calculate(v)
|
||||
record = [cat, stat.min(), stat.max(), stat.mean(), stat.sampleStDev(), stat.sum(), stat.count()]
|
||||
writer.addRecord(record)
|
||||
f = QgsFeature()
|
||||
f.setAttributes([cat, stat.min(), stat.max(), stat.mean(), stat.sampleStDev(), stat.sum(), stat.count()])
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -31,33 +31,31 @@ import sys
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
from qgis.core import (QgsApplication,
|
||||
QgsField,
|
||||
from qgis.core import (QgsField,
|
||||
QgsFeatureSink,
|
||||
QgsGeometry,
|
||||
QgsSpatialIndex,
|
||||
QgsPointXY,
|
||||
NULL,
|
||||
QgsProcessingUtils)
|
||||
QgsProcessing,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterNumber,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterFeatureSink)
|
||||
|
||||
from qgis.PyQt.QtCore import (QVariant)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.parameters import (ParameterVector,
|
||||
ParameterSelection,
|
||||
ParameterNumber)
|
||||
from processing.core.outputs import OutputVector
|
||||
from processing.tools import dataobjects
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
|
||||
class TopoColor(QgisAlgorithm):
|
||||
INPUT_LAYER = 'INPUT_LAYER'
|
||||
INPUT = 'INPUT'
|
||||
MIN_COLORS = 'MIN_COLORS'
|
||||
MIN_DISTANCE = 'MIN_DISTANCE'
|
||||
BALANCE = 'BALANCE'
|
||||
OUTPUT_LAYER = 'OUTPUT_LAYER'
|
||||
OUTPUT = 'OUTPUT'
|
||||
|
||||
def tags(self):
|
||||
return self.tr('topocolor,colors,graph,adjacent,assign').split(',')
|
||||
@ -69,21 +67,23 @@ class TopoColor(QgisAlgorithm):
|
||||
super().__init__()
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.addParameter(ParameterVector(self.INPUT_LAYER,
|
||||
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_POLYGON]))
|
||||
self.addParameter(ParameterNumber(self.MIN_COLORS,
|
||||
self.tr('Minimum number of colors'), 1, 1000, 4))
|
||||
self.addParameter(ParameterNumber(self.MIN_DISTANCE,
|
||||
self.tr('Minimum distance between features'), 0.0, 999999999.0, 0.0))
|
||||
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
|
||||
self.tr('Input layer'), [QgsProcessing.TypeVectorPolygon]))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.MIN_COLORS,
|
||||
self.tr('Minimum number of colors'), minValue=1, maxValue=1000, defaultValue=4))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.MIN_DISTANCE,
|
||||
self.tr('Minimum distance between features'), type=QgsProcessingParameterNumber.Double,
|
||||
minValue=0.0, maxValue=999999999.0, defaultValue=0.0))
|
||||
balance_by = [self.tr('By feature count'),
|
||||
self.tr('By assigned area'),
|
||||
self.tr('By distance between colors')]
|
||||
self.addParameter(ParameterSelection(
|
||||
self.addParameter(QgsProcessingParameterEnum(
|
||||
self.BALANCE,
|
||||
self.tr('Balance color assignment'),
|
||||
balance_by, default=0))
|
||||
options=balance_by, defaultValue=0))
|
||||
|
||||
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Colored'), datatype=[dataobjects.TYPE_VECTOR_POLYGON]))
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Colored'), QgsProcessing.TypeVectorPolygon))
|
||||
|
||||
def name(self):
|
||||
return 'topologicalcoloring'
|
||||
@ -92,18 +92,18 @@ class TopoColor(QgisAlgorithm):
|
||||
return self.tr('Topological coloring')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
|
||||
min_colors = self.getParameterValue(self.MIN_COLORS)
|
||||
balance_by = self.getParameterValue(self.BALANCE)
|
||||
min_distance = self.getParameterValue(self.MIN_DISTANCE)
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
min_colors = self.parameterAsInt(parameters, self.MIN_COLORS, context)
|
||||
balance_by = self.parameterAsEnum(parameters, self.BALANCE, context)
|
||||
min_distance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context)
|
||||
|
||||
fields = layer.fields()
|
||||
fields = source.fields()
|
||||
fields.append(QgsField('color_id', QVariant.Int))
|
||||
|
||||
writer = self.getOutputFromName(
|
||||
self.OUTPUT_LAYER).getVectorWriter(fields, layer.wkbType(), layer.crs(), context)
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, source.wkbType(), source.sourceCrs())
|
||||
|
||||
features = {f.id(): f for f in QgsProcessingUtils.getFeatures(layer, context)}
|
||||
features = {f.id(): f for f in source.getFeatures()}
|
||||
|
||||
topology, id_graph = self.compute_graph(features, feedback, min_distance=min_distance)
|
||||
feature_colors = ColoringAlgorithm.balanced(features,
|
||||
@ -118,6 +118,9 @@ class TopoColor(QgisAlgorithm):
|
||||
total = 20.0 / len(features)
|
||||
current = 0
|
||||
for feature_id, input_feature in features.items():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
output_feature = input_feature
|
||||
attributes = input_feature.attributes()
|
||||
if feature_id in feature_colors:
|
||||
@ -126,11 +129,11 @@ class TopoColor(QgisAlgorithm):
|
||||
attributes.append(NULL)
|
||||
output_feature.setAttributes(attributes)
|
||||
|
||||
writer.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
current += 1
|
||||
feedback.setProgress(80 + int(current * total))
|
||||
|
||||
del writer
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
||||
@staticmethod
|
||||
def compute_graph(features, feedback, create_id_graph=False, min_distance=0):
|
||||
@ -148,6 +151,9 @@ class TopoColor(QgisAlgorithm):
|
||||
|
||||
i = 0
|
||||
for feature_id, f in features_with_geometry.items():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
g = f.geometry()
|
||||
if min_distance > 0:
|
||||
g = g.buffer(min_distance, 5)
|
||||
@ -172,6 +178,9 @@ class TopoColor(QgisAlgorithm):
|
||||
feedback.setProgress(int(i * total))
|
||||
|
||||
for feature_id, f in features_with_geometry.items():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if feature_id not in s.node_edge:
|
||||
s.add_edge(feature_id, None)
|
||||
|
||||
@ -206,6 +215,9 @@ class ColoringAlgorithm:
|
||||
i = 0
|
||||
|
||||
for (feature_id, n) in sorted_by_count:
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
# first work out which already assigned colors are adjacent to this feature
|
||||
adjacent_colors = set()
|
||||
for neighbour in graph.node_edge[feature_id]:
|
||||
@ -240,6 +252,9 @@ class ColoringAlgorithm:
|
||||
# loop through these, and calculate the minimum distance from this feature to the nearest
|
||||
# feature with each assigned color
|
||||
for other_feature_id, c in other_features.items():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
other_geometry = features[other_feature_id].geometry()
|
||||
other_centroid = QgsPointXY(other_geometry.centroid().geometry())
|
||||
|
||||
|
@ -229,7 +229,7 @@ class AlgorithmDialog(AlgorithmDialogBase):
|
||||
feedback.pushInfo(
|
||||
self.tr('Execution completed in {0:0.2f} seconds'.format(time.time() - start_time)))
|
||||
self.buttonCancel.setEnabled(False)
|
||||
self.finish(parameters, context, feedback)
|
||||
self.finish(True, parameters, context, feedback)
|
||||
else:
|
||||
self.buttonCancel.setEnabled(False)
|
||||
self.resetGUI()
|
||||
@ -250,7 +250,7 @@ class AlgorithmDialog(AlgorithmDialogBase):
|
||||
feedback.pushInfo('')
|
||||
|
||||
self.buttonCancel.setEnabled(False)
|
||||
self.finish(results, context, feedback)
|
||||
self.finish(ok, results, context, feedback)
|
||||
|
||||
task = QgsProcessingAlgRunnerTask(self.alg, parameters, context, feedback)
|
||||
task.executed.connect(on_complete)
|
||||
@ -269,8 +269,8 @@ class AlgorithmDialog(AlgorithmDialogBase):
|
||||
self.bar.pushMessage("", self.tr("Wrong or missing parameter value: {0}").format(e.parameter.description()),
|
||||
level=QgsMessageBar.WARNING, duration=5)
|
||||
|
||||
def finish(self, result, context, feedback):
|
||||
keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN)
|
||||
def finish(self, successful, result, context, feedback):
|
||||
keepOpen = not successful or ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN)
|
||||
|
||||
if self.iterateParam is None:
|
||||
|
||||
|
@ -238,7 +238,7 @@ class AlgorithmDialogBase(BASE, WIDGET):
|
||||
self._saveGeometry()
|
||||
super(AlgorithmDialogBase, self).reject()
|
||||
|
||||
def finish(self, context, feedback):
|
||||
def finish(self, successful, result, context, feedback):
|
||||
pass
|
||||
|
||||
def toggleCollapsed(self):
|
||||
|
@ -32,6 +32,7 @@ import os
|
||||
|
||||
from qgis.core import QgsSettings
|
||||
from qgis.PyQt import uic
|
||||
from qgis.PyQt.QtCore import QByteArray
|
||||
from qgis.PyQt.QtWidgets import QDialog, QAbstractItemView, QPushButton, QDialogButtonBox, QFileDialog
|
||||
from qgis.PyQt.QtGui import QStandardItemModel, QStandardItem
|
||||
|
||||
@ -65,7 +66,14 @@ class MultipleFileInputDialog(BASE, WIDGET):
|
||||
self.btnRemove.clicked.connect(lambda: self.removeRows())
|
||||
self.btnRemoveAll.clicked.connect(lambda: self.removeRows(True))
|
||||
|
||||
self.settings = QgsSettings()
|
||||
self.restoreGeometry(self.settings.value("/Processing/multipleFileInputDialogGeometry", QByteArray()))
|
||||
|
||||
self.populateList()
|
||||
self.finished.connect(self.saveWindowGeometry)
|
||||
|
||||
def saveWindowGeometry(self):
|
||||
self.settings.setValue("/Processing/multipleInputDialogGeometry", self.saveGeometry())
|
||||
|
||||
def populateList(self):
|
||||
model = QStandardItemModel()
|
||||
|
@ -29,8 +29,10 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
import os
|
||||
|
||||
from qgis.core import QgsSettings
|
||||
from qgis.PyQt import uic
|
||||
from qgis.PyQt.QtCore import Qt
|
||||
from qgis.PyQt.QtCore import QByteArray
|
||||
from qgis.PyQt.QtWidgets import QDialog, QAbstractItemView, QPushButton, QDialogButtonBox
|
||||
from qgis.PyQt.QtGui import QStandardItemModel, QStandardItem
|
||||
|
||||
@ -71,7 +73,14 @@ class MultipleInputDialog(BASE, WIDGET):
|
||||
self.btnClearSelection.clicked.connect(lambda: self.selectAll(False))
|
||||
self.btnToggleSelection.clicked.connect(self.toggleSelection)
|
||||
|
||||
self.settings = QgsSettings()
|
||||
self.restoreGeometry(self.settings.value("/Processing/multipleInputDialogGeometry", QByteArray()))
|
||||
|
||||
self.populateList()
|
||||
self.finished.connect(self.saveWindowGeometry)
|
||||
|
||||
def saveWindowGeometry(self):
|
||||
self.settings.setValue("/Processing/multipleInputDialogGeometry", self.saveGeometry())
|
||||
|
||||
def populateList(self):
|
||||
model = QStandardItemModel()
|
||||
|
@ -27,7 +27,7 @@ __copyright__ = '(C) 2017, Nyall Dawson'
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
from qgis.core import (QgsProcessing,
|
||||
QgsProcessingParameterDefinition,
|
||||
QgsProviderRegistry,
|
||||
QgsProcessingFeatureSourceDefinition,
|
||||
QgsVectorFileWriter)
|
||||
from qgis.PyQt.QtCore import QCoreApplication
|
||||
@ -55,22 +55,29 @@ def getFileFilter(param):
|
||||
exts = QgsVectorFileWriter.supportedFormatExtensions()
|
||||
for i in range(len(exts)):
|
||||
exts[i] = tr('{0} files (*.{1})', 'QgsProcessingParameterMultipleLayers').format(exts[i].upper(), exts[i].lower())
|
||||
return ';;'.join(exts)
|
||||
elif param.type() in ('raster', 'rasterDestination'):
|
||||
return tr('All files (*.*)') + ';;' + ';;'.join(exts)
|
||||
elif param.type() == 'raster':
|
||||
return QgsProviderRegistry.instance().fileRasterFilters()
|
||||
elif param.type() == 'rasterDestination':
|
||||
exts = dataobjects.getSupportedOutputRasterLayerExtensions()
|
||||
for i in range(len(exts)):
|
||||
exts[i] = tr('{0} files (*.{1})', 'QgsProcessingParameterRasterDestination').format(exts[i].upper(), exts[i].lower())
|
||||
return ';;'.join(exts)
|
||||
return tr('All files (*.*)') + ';;' + ';;'.join(exts)
|
||||
elif param.type() == 'table':
|
||||
exts = ['csv', 'dbf']
|
||||
for i in range(len(exts)):
|
||||
exts[i] = tr('{0} files (*.{1})', 'ParameterTable').format(exts[i].upper(), exts[i].lower())
|
||||
return ';;'.join(exts)
|
||||
return tr('All files (*.*)') + ';;' + ';;'.join(exts)
|
||||
elif param.type() == 'sink':
|
||||
exts = QgsVectorFileWriter.supportedFormatExtensions()
|
||||
for i in range(len(exts)):
|
||||
exts[i] = tr('{0} files (*.{1})', 'ParameterVector').format(exts[i].upper(), exts[i].lower())
|
||||
return ';;'.join(exts)
|
||||
return tr('All files (*.*)') + ';;' + ';;'.join(exts)
|
||||
elif param.type() == 'source':
|
||||
return QgsProviderRegistry.instance().fileVectorFilters()
|
||||
elif param.type() == 'vector':
|
||||
return QgsProviderRegistry.instance().fileVectorFilters()
|
||||
elif param.type() == 'fileOut':
|
||||
return param.fileFilter()
|
||||
return tr('All files (*.*)') + ';;' + param.fileFilter()
|
||||
|
||||
return ''
|
||||
|
@ -218,8 +218,7 @@ class WidgetWrapper(QObject):
|
||||
path = ''
|
||||
|
||||
filename, selected_filter = QFileDialog.getOpenFileName(self.widget, self.tr('Select file'),
|
||||
path, self.tr(
|
||||
'All files (*.*);;') + getFileFilter(self.param))
|
||||
path, getFileFilter(self.param))
|
||||
if filename:
|
||||
settings.setValue('/Processing/LastInputPath',
|
||||
os.path.dirname(str(filename)))
|
||||
|
@ -43,6 +43,7 @@ import tempfile
|
||||
|
||||
from osgeo.gdalconst import GA_ReadOnly
|
||||
from numpy import nan_to_num
|
||||
from copy import deepcopy
|
||||
|
||||
import processing
|
||||
|
||||
@ -186,7 +187,10 @@ class AlgorithmsTest(object):
|
||||
if param['type'] in ['vector', 'file', 'table', 'regex']:
|
||||
outdir = tempfile.mkdtemp()
|
||||
self.cleanup_paths.append(outdir)
|
||||
basename = os.path.basename(param['name'])
|
||||
if isinstance(param['name'], str):
|
||||
basename = os.path.basename(param['name'])
|
||||
else:
|
||||
basename = os.path.basename(param['name'][0])
|
||||
filepath = os.path.join(outdir, basename)
|
||||
return filepath
|
||||
elif param['type'] == 'rasterhash':
|
||||
@ -198,6 +202,19 @@ class AlgorithmsTest(object):
|
||||
|
||||
raise KeyError("Unknown type '{}' specified for parameter".format(param['type']))
|
||||
|
||||
def load_layers(self, id, param):
|
||||
layers = []
|
||||
if param['type'] in ('vector', 'table') and isinstance(param['name'], str):
|
||||
layers.append(self.load_layer(id, param))
|
||||
elif param['type'] in ('vector', 'table'):
|
||||
for n in param['name']:
|
||||
layer_param = deepcopy(param)
|
||||
layer_param['name'] = n
|
||||
layers.append(self.load_layer(id, layer_param))
|
||||
else:
|
||||
layers.append(self.load_layer(id, param))
|
||||
return layers
|
||||
|
||||
def load_layer(self, id, param):
|
||||
"""
|
||||
Loads a layer which was specified as parameter.
|
||||
@ -253,7 +270,7 @@ class AlgorithmsTest(object):
|
||||
self.assertTrue(result_lyr.isValid())
|
||||
continue
|
||||
|
||||
expected_lyr = self.load_layer(id, expected_result)
|
||||
expected_lyrs = self.load_layers(id, expected_result)
|
||||
if 'in_place_result' in expected_result:
|
||||
result_lyr = QgsProcessingUtils.mapLayerFromString(self.in_place_layers[id], context)
|
||||
self.assertTrue(result_lyr.isValid(), self.in_place_layers[id])
|
||||
@ -270,8 +287,17 @@ class AlgorithmsTest(object):
|
||||
self.assertTrue(result_lyr, results[id])
|
||||
|
||||
compare = expected_result.get('compare', {})
|
||||
pk = expected_result.get('pk', None)
|
||||
|
||||
self.assertLayersEqual(expected_lyr, result_lyr, compare=compare)
|
||||
if len(expected_lyrs) == 1:
|
||||
self.assertLayersEqual(expected_lyrs[0], result_lyr, compare=compare, pk=pk)
|
||||
else:
|
||||
res = False
|
||||
for l in expected_lyrs:
|
||||
if self.checkLayersEqual(l, result_lyr, compare=compare, pk=pk):
|
||||
res = True
|
||||
break
|
||||
self.assertTrue(res, 'Could not find matching layer in expected results')
|
||||
|
||||
elif 'rasterhash' == expected_result['type']:
|
||||
print("id:{} result:{}".format(id, results[id]))
|
||||
@ -279,7 +305,10 @@ class AlgorithmsTest(object):
|
||||
dataArray = nan_to_num(dataset.ReadAsArray(0))
|
||||
strhash = hashlib.sha224(dataArray.data).hexdigest()
|
||||
|
||||
self.assertEqual(strhash, expected_result['hash'])
|
||||
if not isinstance(expected_result['hash'], str):
|
||||
self.assertTrue(strhash in expected_result['hash'])
|
||||
else:
|
||||
self.assertEqual(strhash, expected_result['hash'])
|
||||
elif 'file' == expected_result['type']:
|
||||
expected_filepath = self.filepath_from_param(expected_result)
|
||||
result_filepath = results[id]
|
||||
|
22
python/plugins/processing/tests/testdata/custom/hub_points.gfs
vendored
Normal file
22
python/plugins/processing/tests/testdata/custom/hub_points.gfs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>hub_points</Name>
|
||||
<ElementPath>hub_points</ElementPath>
|
||||
<!--POINT-->
|
||||
<GeometryType>1</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>3</FeatureCount>
|
||||
<ExtentXMin>1.34481</ExtentXMin>
|
||||
<ExtentXMax>6.29897</ExtentXMax>
|
||||
<ExtentYMin>-1.25947</ExtentYMin>
|
||||
<ExtentYMax>2.27221</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>name</Name>
|
||||
<ElementPath>name</ElementPath>
|
||||
<Type>String</Type>
|
||||
<Width>6</Width>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
32
python/plugins/processing/tests/testdata/custom/hub_points.gml
vendored
Normal file
32
python/plugins/processing/tests/testdata/custom/hub_points.gml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ hub_points.xsd"
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>1.344807662693645</gml:X><gml:Y>-1.259467184083282</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>6.298968246635251</gml:X><gml:Y>2.272211648033507</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:hub_points fid="hub_points.0">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1.34480766269365,-1.25946718408328</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:name>point1</ogr:name>
|
||||
</ogr:hub_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_points fid="hub_points.1">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>6.29896824663525,0.138489020296281</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:name>point2</ogr:name>
|
||||
</ogr:hub_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_points fid="hub_points.2">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.12290985247467,2.27221164803351</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:name>point3</ogr:name>
|
||||
</ogr:hub_points>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
27
python/plugins/processing/tests/testdata/custom/spoke_points.gfs
vendored
Normal file
27
python/plugins/processing/tests/testdata/custom/spoke_points.gfs
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>spoke_points</Name>
|
||||
<ElementPath>spoke_points</ElementPath>
|
||||
<!--POINT-->
|
||||
<GeometryType>1</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>7</FeatureCount>
|
||||
<ExtentXMin>1.27875</ExtentXMin>
|
||||
<ExtentXMax>6.82625</ExtentXMax>
|
||||
<ExtentYMin>-4.16750</ExtentYMin>
|
||||
<ExtentYMax>3.88250</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>id</Name>
|
||||
<ElementPath>id</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>name</Name>
|
||||
<ElementPath>name</ElementPath>
|
||||
<Type>String</Type>
|
||||
<Width>8</Width>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
63
python/plugins/processing/tests/testdata/custom/spoke_points.gml
vendored
Normal file
63
python/plugins/processing/tests/testdata/custom/spoke_points.gml
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ spoke_points.xsd"
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>1.27875</gml:X><gml:Y>-4.1675</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>6.826249999999999</gml:X><gml:Y>3.882499999999999</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:spoke_points fid="spoke_points.0">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5.07625,-2.1725</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>1</ogr:id>
|
||||
<ogr:name>point 1</ogr:name>
|
||||
</ogr:spoke_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:spoke_points fid="spoke_points.1">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5.82,3.8825</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>2</ogr:id>
|
||||
<ogr:name>point 2</ogr:name>
|
||||
</ogr:spoke_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:spoke_points fid="spoke_points.2">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1.62,1.4675</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>3</ogr:id>
|
||||
<ogr:name>point 3</ogr:name>
|
||||
</ogr:spoke_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:spoke_points fid="spoke_points.3">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>6.68625,1.23125</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:name>point 4</ogr:name>
|
||||
</ogr:spoke_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:spoke_points fid="spoke_points.4">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1.27875,-3.66875</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:name>point 4a</ogr:name>
|
||||
</ogr:spoke_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:spoke_points fid="spoke_points.5">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.81625,-4.1675</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:name>point 4b</ogr:name>
|
||||
</ogr:spoke_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:spoke_points fid="spoke_points.6">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>6.82625,-2.79375</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>8</ogr:id>
|
||||
<ogr:name>point 8</ogr:name>
|
||||
</ogr:spoke_points>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
16
python/plugins/processing/tests/testdata/expected/gridify_lines.gfs
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/gridify_lines.gfs
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>gridify_lines</Name>
|
||||
<ElementPath>gridify_lines</ElementPath>
|
||||
<!--LINESTRING-->
|
||||
<GeometryType>2</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>7</FeatureCount>
|
||||
<ExtentXMin>2.00000</ExtentXMin>
|
||||
<ExtentXMax>12.00000</ExtentXMax>
|
||||
<ExtentYMin>-4.00000</ExtentYMin>
|
||||
<ExtentYMax>4.00000</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
46
python/plugins/processing/tests/testdata/expected/gridify_lines.gml
vendored
Normal file
46
python/plugins/processing/tests/testdata/expected/gridify_lines.gml
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>2</gml:X><gml:Y>-4</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>12</gml:X><gml:Y>4</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_lines fid="lines.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,2 8,2 8,4 12,4</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:gridify_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_lines fid="lines.1">
|
||||
</ogr:gridify_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_lines fid="lines.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 2,2 4,2 4,4</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:gridify_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_lines fid="lines.3">
|
||||
</ogr:gridify_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_lines fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>8,-4 10,-4</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:gridify_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_lines fid="lines.5">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-4 10,0</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:gridify_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_lines fid="lines.6">
|
||||
</ogr:gridify_lines>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
32
python/plugins/processing/tests/testdata/expected/gridify_polys.gfs
vendored
Normal file
32
python/plugins/processing/tests/testdata/expected/gridify_polys.gfs
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>gridify_polys</Name>
|
||||
<ElementPath>gridify_polys</ElementPath>
|
||||
<!--POLYGON-->
|
||||
<GeometryType>3</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>6</FeatureCount>
|
||||
<ExtentXMin>0.00000</ExtentXMin>
|
||||
<ExtentXMax>10.00000</ExtentXMax>
|
||||
<ExtentYMin>-4.00000</ExtentYMin>
|
||||
<ExtentYMax>6.00000</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>name</Name>
|
||||
<ElementPath>name</ElementPath>
|
||||
<Type>String</Type>
|
||||
<Width>5</Width>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>intval</Name>
|
||||
<ElementPath>intval</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>floatval</Name>
|
||||
<ElementPath>floatval</ElementPath>
|
||||
<Type>Real</Type>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
57
python/plugins/processing/tests/testdata/expected/gridify_polys.gml
vendored
Normal file
57
python/plugins/processing/tests/testdata/expected/gridify_polys.gml
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>-0</gml:X><gml:Y>-4</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>10</gml:X><gml:Y>6</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_polys fid="polys.0">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,0 0,4 4,4 4,2 2,2 2,0 0,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:name>aaaaa</ogr:name>
|
||||
<ogr:intval>33</ogr:intval>
|
||||
<ogr:floatval>44.123456</ogr:floatval>
|
||||
</ogr:gridify_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_polys fid="polys.1">
|
||||
<ogr:name>Aaaaa</ogr:name>
|
||||
<ogr:intval>-33</ogr:intval>
|
||||
<ogr:floatval>0</ogr:floatval>
|
||||
</ogr:gridify_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_polys fid="polys.2">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,4 2,6 4,6 4,4 2,4</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:name>bbaaa</ogr:name>
|
||||
<ogr:floatval>0.123</ogr:floatval>
|
||||
</ogr:gridify_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_polys fid="polys.3">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,0 10,0 10,-4 6,-4 6,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:name>ASDF</ogr:name>
|
||||
<ogr:intval>0</ogr:intval>
|
||||
</ogr:gridify_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_polys fid="polys.4">
|
||||
<ogr:intval>120</ogr:intval>
|
||||
<ogr:floatval>-100291.43213</ogr:floatval>
|
||||
</ogr:gridify_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:gridify_polys fid="polys.5">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4,2 6,0 6,-4 2,0 2,2 4,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:name>elim</ogr:name>
|
||||
<ogr:intval>2</ogr:intval>
|
||||
<ogr:floatval>3.33</ogr:floatval>
|
||||
</ogr:gridify_polys>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
37
python/plugins/processing/tests/testdata/expected/hub_distance_lines.gfs
vendored
Normal file
37
python/plugins/processing/tests/testdata/expected/hub_distance_lines.gfs
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>hub_distance_lines</Name>
|
||||
<ElementPath>hub_distance_lines</ElementPath>
|
||||
<!--LINESTRING-->
|
||||
<GeometryType>2</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>9</FeatureCount>
|
||||
<ExtentXMin>0.00000</ExtentXMin>
|
||||
<ExtentXMax>8.00000</ExtentXMax>
|
||||
<ExtentYMin>-5.00000</ExtentYMin>
|
||||
<ExtentYMax>3.00000</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>id</Name>
|
||||
<ElementPath>id</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>id2</Name>
|
||||
<ElementPath>id2</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>HubName</Name>
|
||||
<ElementPath>HubName</ElementPath>
|
||||
<Type>String</Type>
|
||||
<Width>6</Width>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>HubDist</Name>
|
||||
<ElementPath>HubDist</ElementPath>
|
||||
<Type>Real</Type>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
95
python/plugins/processing/tests/testdata/expected/hub_distance_lines.gml
vendored
Normal file
95
python/plugins/processing/tests/testdata/expected/hub_distance_lines.gml
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_lines fid="points.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1,1 1.34480766269365,-1.25946718408328</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>1</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:HubName>point1</ogr:HubName>
|
||||
<ogr:HubDist>254434.675423572</ogr:HubDist>
|
||||
</ogr:hub_distance_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_lines fid="points.1">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,3 3.12290985247467,2.27221164803351</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>2</ogr:id>
|
||||
<ogr:id2>1</ogr:id2>
|
||||
<ogr:HubName>point3</ogr:HubName>
|
||||
<ogr:HubDist>82164.2455422206</ogr:HubDist>
|
||||
</ogr:hub_distance_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_lines fid="points.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,2 3.12290985247467,2.27221164803351</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>3</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point3</ogr:HubName>
|
||||
<ogr:HubDist>128622.227687308</ogr:HubDist>
|
||||
</ogr:hub_distance_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_lines fid="points.3">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5,2 3.12290985247467,2.27221164803351</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:HubName>point3</ogr:HubName>
|
||||
<ogr:HubDist>211142.486929284</ogr:HubDist>
|
||||
</ogr:hub_distance_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_lines fid="points.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>4,1 3.12290985247467,2.27221164803351</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>5</ogr:id>
|
||||
<ogr:id2>1</ogr:id2>
|
||||
<ogr:HubName>point3</ogr:HubName>
|
||||
<ogr:HubDist>172016.876891364</ogr:HubDist>
|
||||
</ogr:hub_distance_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_lines fid="points.5">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>0,-5 1.34480766269365,-1.25946718408328</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>6</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point1</ogr:HubName>
|
||||
<ogr:HubDist>442487.532089586</ogr:HubDist>
|
||||
</ogr:hub_distance_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_lines fid="points.6">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>8,-1 6.29896824663525,0.138489020296281</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>7</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point2</ogr:HubName>
|
||||
<ogr:HubDist>227856.24000978</ogr:HubDist>
|
||||
</ogr:hub_distance_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_lines fid="points.7">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-1 6.29896824663525,0.138489020296281</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>8</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point2</ogr:HubName>
|
||||
<ogr:HubDist>148835.564980152</ogr:HubDist>
|
||||
</ogr:hub_distance_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_lines fid="points.8">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>0,-1 1.34480766269365,-1.25946718408328</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>9</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point1</ogr:HubName>
|
||||
<ogr:HubDist>152464.26003518</ogr:HubDist>
|
||||
</ogr:hub_distance_lines>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
37
python/plugins/processing/tests/testdata/expected/hub_distance_points.gfs
vendored
Normal file
37
python/plugins/processing/tests/testdata/expected/hub_distance_points.gfs
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>hub_distance_points</Name>
|
||||
<ElementPath>hub_distance_points</ElementPath>
|
||||
<!--POINT-->
|
||||
<GeometryType>1</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>9</FeatureCount>
|
||||
<ExtentXMin>0.00000</ExtentXMin>
|
||||
<ExtentXMax>8.00000</ExtentXMax>
|
||||
<ExtentYMin>-5.00000</ExtentYMin>
|
||||
<ExtentYMax>3.00000</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>id</Name>
|
||||
<ElementPath>id</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>id2</Name>
|
||||
<ElementPath>id2</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>HubName</Name>
|
||||
<ElementPath>HubName</ElementPath>
|
||||
<Type>String</Type>
|
||||
<Width>6</Width>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>HubDist</Name>
|
||||
<ElementPath>HubDist</ElementPath>
|
||||
<Type>Real</Type>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
95
python/plugins/processing/tests/testdata/expected/hub_distance_points.gml
vendored
Normal file
95
python/plugins/processing/tests/testdata/expected/hub_distance_points.gml
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_points fid="points.0">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>1</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:HubName>point1</ogr:HubName>
|
||||
<ogr:HubDist>254434.675423572</ogr:HubDist>
|
||||
</ogr:hub_distance_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_points fid="points.1">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>2</ogr:id>
|
||||
<ogr:id2>1</ogr:id2>
|
||||
<ogr:HubName>point3</ogr:HubName>
|
||||
<ogr:HubDist>82164.2455422206</ogr:HubDist>
|
||||
</ogr:hub_distance_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_points fid="points.2">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>3</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point3</ogr:HubName>
|
||||
<ogr:HubDist>128622.227687308</ogr:HubDist>
|
||||
</ogr:hub_distance_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_points fid="points.3">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5,2</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:HubName>point3</ogr:HubName>
|
||||
<ogr:HubDist>211142.486929284</ogr:HubDist>
|
||||
</ogr:hub_distance_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_points fid="points.4">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>5</ogr:id>
|
||||
<ogr:id2>1</ogr:id2>
|
||||
<ogr:HubName>point3</ogr:HubName>
|
||||
<ogr:HubDist>172016.876891364</ogr:HubDist>
|
||||
</ogr:hub_distance_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_points fid="points.5">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-5</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>6</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point1</ogr:HubName>
|
||||
<ogr:HubDist>442487.532089586</ogr:HubDist>
|
||||
</ogr:hub_distance_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_points fid="points.6">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>7</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point2</ogr:HubName>
|
||||
<ogr:HubDist>227856.24000978</ogr:HubDist>
|
||||
</ogr:hub_distance_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_points fid="points.7">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>8</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point2</ogr:HubName>
|
||||
<ogr:HubDist>148835.564980152</ogr:HubDist>
|
||||
</ogr:hub_distance_points>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_distance_points fid="points.8">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:id>9</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:HubName>point1</ogr:HubName>
|
||||
<ogr:HubDist>152464.26003518</ogr:HubDist>
|
||||
</ogr:hub_distance_points>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
43
python/plugins/processing/tests/testdata/expected/hub_lines.gfs
vendored
Normal file
43
python/plugins/processing/tests/testdata/expected/hub_lines.gfs
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>hub_lines</Name>
|
||||
<ElementPath>hub_lines</ElementPath>
|
||||
<!--LINESTRING-->
|
||||
<GeometryType>2</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>7</FeatureCount>
|
||||
<ExtentXMin>1.00000</ExtentXMin>
|
||||
<ExtentXMax>7.00000</ExtentXMax>
|
||||
<ExtentYMin>-4.16750</ExtentYMin>
|
||||
<ExtentYMax>3.88250</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>id</Name>
|
||||
<ElementPath>id</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>id2</Name>
|
||||
<ElementPath>id2</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>fid_2</Name>
|
||||
<ElementPath>fid_2</ElementPath>
|
||||
<Type>String</Type>
|
||||
<Width>14</Width>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>id_2</Name>
|
||||
<ElementPath>id_2</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>name</Name>
|
||||
<ElementPath>name</ElementPath>
|
||||
<Type>String</Type>
|
||||
<Width>8</Width>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
84
python/plugins/processing/tests/testdata/expected/hub_lines.gml
vendored
Normal file
84
python/plugins/processing/tests/testdata/expected/hub_lines.gml
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>1</gml:X><gml:Y>-4.1675</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>7</gml:X><gml:Y>3.8825</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines fid="points.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1,1 5.07625,-2.1725</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>1</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:fid_2>spoke_points.0</ogr:fid_2>
|
||||
<ogr:id_2>1</ogr:id_2>
|
||||
<ogr:name>point 1</ogr:name>
|
||||
</ogr:hub_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines fid="points.1">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,3 5.82,3.8825</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>2</ogr:id>
|
||||
<ogr:id2>1</ogr:id2>
|
||||
<ogr:fid_2>spoke_points.1</ogr:fid_2>
|
||||
<ogr:id_2>2</ogr:id_2>
|
||||
<ogr:name>point 2</ogr:name>
|
||||
</ogr:hub_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines fid="points.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,2 1.62,1.4675</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>3</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:fid_2>spoke_points.2</ogr:fid_2>
|
||||
<ogr:id_2>3</ogr:id_2>
|
||||
<ogr:name>point 3</ogr:name>
|
||||
</ogr:hub_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines fid="points.3">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5,2 6.68625,1.23125</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:fid_2>spoke_points.3</ogr:fid_2>
|
||||
<ogr:id_2>4</ogr:id_2>
|
||||
<ogr:name>point 4</ogr:name>
|
||||
</ogr:hub_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines fid="points.3">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5,2 1.27875,-3.66875</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:fid_2>spoke_points.4</ogr:fid_2>
|
||||
<ogr:id_2>4</ogr:id_2>
|
||||
<ogr:name>point 4a</ogr:name>
|
||||
</ogr:hub_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines fid="points.3">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5,2 3.81625,-4.1675</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:fid_2>spoke_points.5</ogr:fid_2>
|
||||
<ogr:id_2>4</ogr:id_2>
|
||||
<ogr:name>point 4b</ogr:name>
|
||||
</ogr:hub_lines>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines fid="points.7">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-1 6.82625,-2.79375</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>8</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:fid_2>spoke_points.6</ogr:fid_2>
|
||||
<ogr:id_2>8</ogr:id_2>
|
||||
<ogr:name>point 8</ogr:name>
|
||||
</ogr:hub_lines>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
26
python/plugins/processing/tests/testdata/expected/points_to_path.gfs
vendored
Normal file
26
python/plugins/processing/tests/testdata/expected/points_to_path.gfs
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>points_to_path</Name>
|
||||
<ElementPath>points_to_path</ElementPath>
|
||||
<!--LINESTRING-->
|
||||
<GeometryType>2</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>1</FeatureCount>
|
||||
<ExtentXMin>0.00000</ExtentXMin>
|
||||
<ExtentXMax>8.00000</ExtentXMax>
|
||||
<ExtentYMin>-5.00000</ExtentYMin>
|
||||
<ExtentYMax>3.00000</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>begin</Name>
|
||||
<ElementPath>begin</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>end</Name>
|
||||
<ElementPath>end</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
21
python/plugins/processing/tests/testdata/expected/points_to_path.gml
vendored
Normal file
21
python/plugins/processing/tests/testdata/expected/points_to_path.gml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:points_to_path fid="points_to_path.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1,1 3,3 2,2 5,2 4,1 0,-5 8,-1 7,-1 0,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:begin>1</ogr:begin>
|
||||
<ogr:end>9</ogr:end>
|
||||
</ogr:points_to_path>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
31
python/plugins/processing/tests/testdata/expected/points_to_path_grouped.gfs
vendored
Normal file
31
python/plugins/processing/tests/testdata/expected/points_to_path_grouped.gfs
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>points_to_path_grouped</Name>
|
||||
<ElementPath>points_to_path_grouped</ElementPath>
|
||||
<!--LINESTRING-->
|
||||
<GeometryType>2</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>3</FeatureCount>
|
||||
<ExtentXMin>0.00000</ExtentXMin>
|
||||
<ExtentXMax>8.00000</ExtentXMax>
|
||||
<ExtentYMin>-5.00000</ExtentYMin>
|
||||
<ExtentYMax>3.00000</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>id2</Name>
|
||||
<ElementPath>id2</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>begin</Name>
|
||||
<ElementPath>begin</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>end</Name>
|
||||
<ElementPath>end</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
38
python/plugins/processing/tests/testdata/expected/points_to_path_grouped.gml
vendored
Normal file
38
python/plugins/processing/tests/testdata/expected/points_to_path_grouped.gml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:points_to_path_grouped fid="points_to_path_grouped.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1,1 5,2</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:begin>1</ogr:begin>
|
||||
<ogr:end>4</ogr:end>
|
||||
</ogr:points_to_path_grouped>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:points_to_path_grouped fid="points_to_path_grouped.1">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,3 4,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id2>1</ogr:id2>
|
||||
<ogr:begin>2</ogr:begin>
|
||||
<ogr:end>5</ogr:end>
|
||||
</ogr:points_to_path_grouped>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:points_to_path_grouped fid="points_to_path_grouped.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,2 0,-5 8,-1 7,-1 0,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:begin>3</ogr:begin>
|
||||
<ogr:end>9</ogr:end>
|
||||
</ogr:points_to_path_grouped>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
31
python/plugins/processing/tests/testdata/expected/points_to_path_grouped2.gfs
vendored
Normal file
31
python/plugins/processing/tests/testdata/expected/points_to_path_grouped2.gfs
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>points_to_path_grouped</Name>
|
||||
<ElementPath>points_to_path_grouped</ElementPath>
|
||||
<!--LINESTRING-->
|
||||
<GeometryType>2</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>3</FeatureCount>
|
||||
<ExtentXMin>0.00000</ExtentXMin>
|
||||
<ExtentXMax>8.00000</ExtentXMax>
|
||||
<ExtentYMin>-5.00000</ExtentYMin>
|
||||
<ExtentYMax>3.00000</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>id2</Name>
|
||||
<ElementPath>id2</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>begin</Name>
|
||||
<ElementPath>begin</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>end</Name>
|
||||
<ElementPath>end</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
39
python/plugins/processing/tests/testdata/expected/points_to_path_grouped2.gml
vendored
Normal file
39
python/plugins/processing/tests/testdata/expected/points_to_path_grouped2.gml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:points_to_path_grouped fid="points_to_path_grouped.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,2 0,-5 8,-1 7,-1 0,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:begin>3</ogr:begin>
|
||||
<ogr:end>9</ogr:end>
|
||||
</ogr:points_to_path_grouped>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:points_to_path_grouped fid="points_to_path_grouped.1">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,3 4,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id2>1</ogr:id2>
|
||||
<ogr:begin>2</ogr:begin>
|
||||
<ogr:end>5</ogr:end>
|
||||
</ogr:points_to_path_grouped>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:points_to_path_grouped fid="points_to_path_grouped.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1,1 5,2</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:begin>1</ogr:begin>
|
||||
<ogr:end>4</ogr:end>
|
||||
</ogr:points_to_path_grouped>
|
||||
</gml:featureMember>
|
||||
|
||||
</ogr:FeatureCollection>
|
45
python/plugins/processing/tests/testdata/expected/stats_by_category.gfs
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/stats_by_category.gfs
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>stats_by_category</Name>
|
||||
<ElementPath>stats_by_category</ElementPath>
|
||||
<GeometryType>100</GeometryType>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>3</FeatureCount>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>id2</Name>
|
||||
<ElementPath>id2</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>min</Name>
|
||||
<ElementPath>min</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>max</Name>
|
||||
<ElementPath>max</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>mean</Name>
|
||||
<ElementPath>mean</ElementPath>
|
||||
<Type>Real</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>stddev</Name>
|
||||
<ElementPath>stddev</ElementPath>
|
||||
<Type>Real</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>sum</Name>
|
||||
<ElementPath>sum</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>count</Name>
|
||||
<ElementPath>count</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
42
python/plugins/processing/tests/testdata/expected/stats_by_category.gml
vendored
Normal file
42
python/plugins/processing/tests/testdata/expected/stats_by_category.gml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy><gml:null>missing</gml:null></gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:stats_by_category fid="stats_by_category.0">
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:min>1</ogr:min>
|
||||
<ogr:max>4</ogr:max>
|
||||
<ogr:mean>2.5</ogr:mean>
|
||||
<ogr:stddev>2.12132034355964</ogr:stddev>
|
||||
<ogr:sum>5</ogr:sum>
|
||||
<ogr:count>2</ogr:count>
|
||||
</ogr:stats_by_category>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:stats_by_category fid="stats_by_category.1">
|
||||
<ogr:id2>1</ogr:id2>
|
||||
<ogr:min>2</ogr:min>
|
||||
<ogr:max>5</ogr:max>
|
||||
<ogr:mean>3.5</ogr:mean>
|
||||
<ogr:stddev>2.12132034355964</ogr:stddev>
|
||||
<ogr:sum>7</ogr:sum>
|
||||
<ogr:count>2</ogr:count>
|
||||
</ogr:stats_by_category>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:stats_by_category fid="stats_by_category.2">
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:min>3</ogr:min>
|
||||
<ogr:max>9</ogr:max>
|
||||
<ogr:mean>6.6</ogr:mean>
|
||||
<ogr:stddev>2.30217288664427</ogr:stddev>
|
||||
<ogr:sum>33</ogr:sum>
|
||||
<ogr:count>5</ogr:count>
|
||||
</ogr:stats_by_category>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
46
python/plugins/processing/tests/testdata/expected/topocolor_polys2.gfs
vendored
Normal file
46
python/plugins/processing/tests/testdata/expected/topocolor_polys2.gfs
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<GMLFeatureClassList>
|
||||
<GMLFeatureClass>
|
||||
<Name>topocolor_polys</Name>
|
||||
<ElementPath>topocolor_polys</ElementPath>
|
||||
<!--POLYGON-->
|
||||
<GeometryType>3</GeometryType>
|
||||
<SRSName>EPSG:4326</SRSName>
|
||||
<DatasetSpecificInfo>
|
||||
<FeatureCount>11</FeatureCount>
|
||||
<ExtentXMin>-0.76065</ExtentXMin>
|
||||
<ExtentXMax>14.23935</ExtentXMax>
|
||||
<ExtentYMin>-6.11331</ExtentYMin>
|
||||
<ExtentYMax>5.88669</ExtentYMax>
|
||||
</DatasetSpecificInfo>
|
||||
<PropertyDefn>
|
||||
<Name>left</Name>
|
||||
<ElementPath>left</ElementPath>
|
||||
<Type>Real</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>top</Name>
|
||||
<ElementPath>top</ElementPath>
|
||||
<Type>Real</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>right</Name>
|
||||
<ElementPath>right</ElementPath>
|
||||
<Type>Real</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>bottom</Name>
|
||||
<ElementPath>bottom</ElementPath>
|
||||
<Type>Real</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>id</Name>
|
||||
<ElementPath>id</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
<PropertyDefn>
|
||||
<Name>color_id</Name>
|
||||
<ElementPath>color_id</ElementPath>
|
||||
<Type>Integer</Type>
|
||||
</PropertyDefn>
|
||||
</GMLFeatureClass>
|
||||
</GMLFeatureClassList>
|
133
python/plugins/processing/tests/testdata/expected/topocolor_polys2.gml
vendored
Normal file
133
python/plugins/processing/tests/testdata/expected/topocolor_polys2.gml
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=""
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>-0.760650357995228</gml:X><gml:Y>-6.11330548926014</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>14.2393496420048</gml:X><gml:Y>5.88669451073986</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.0">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-0.760650357995228,-0.113305489260142 2.23934964200477,-0.113305489260142 2.23934964200477,-3.11330548926014 -0.760650357995228,-3.11330548926014 -0.760650357995228,-0.113305489260142</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>-0.76065</ogr:left>
|
||||
<ogr:top>-0.11331</ogr:top>
|
||||
<ogr:right>2.23935</ogr:right>
|
||||
<ogr:bottom>-3.11331</ogr:bottom>
|
||||
<ogr:id>3</ogr:id>
|
||||
<ogr:color_id>1</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.1">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-0.760650357995228,-3.11330548926014 2.23934964200477,-3.11330548926014 2.23934964200477,-6.11330548926014 -0.760650357995228,-6.11330548926014 -0.760650357995228,-3.11330548926014</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>-0.76065</ogr:left>
|
||||
<ogr:top>-3.11331</ogr:top>
|
||||
<ogr:right>2.23935</ogr:right>
|
||||
<ogr:bottom>-6.11331</ogr:bottom>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:color_id>3</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.2">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5.23934964200477,-0.113305489260142 8.23934964200477,-0.113305489260142 8.23934964200477,-3.11330548926014 5.23934964200477,-3.11330548926014 5.23934964200477,-0.113305489260142</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>5.23935</ogr:left>
|
||||
<ogr:top>-0.11331</ogr:top>
|
||||
<ogr:right>8.23935</ogr:right>
|
||||
<ogr:bottom>-3.11331</ogr:bottom>
|
||||
<ogr:id>11</ogr:id>
|
||||
<ogr:color_id>5</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.3">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5.23934964200477,-3.11330548926014 8.23934964200477,-3.11330548926014 8.23934964200477,-6.11330548926014 5.23934964200477,-6.11330548926014 5.23934964200477,-3.11330548926014</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>5.23935</ogr:left>
|
||||
<ogr:top>-3.11331</ogr:top>
|
||||
<ogr:right>8.23935</ogr:right>
|
||||
<ogr:bottom>-6.11331</ogr:bottom>
|
||||
<ogr:id>12</ogr:id>
|
||||
<ogr:color_id>4</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.4">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>8.23934964200477,-3.11330548926014 11.2393496420048,-3.11330548926014 11.2393496420048,-6.11330548926014 8.23934964200477,-6.11330548926014 8.23934964200477,-3.11330548926014</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>8.23935</ogr:left>
|
||||
<ogr:top>-3.11331</ogr:top>
|
||||
<ogr:right>11.23935</ogr:right>
|
||||
<ogr:bottom>-6.11331</ogr:bottom>
|
||||
<ogr:id>16</ogr:id>
|
||||
<ogr:color_id>3</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.5">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>11.2393496420048,-0.113305489260142 14.2393496420048,-0.113305489260142 14.2393496420048,-3.11330548926014 11.2393496420048,-3.11330548926014 11.2393496420048,-0.113305489260142</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>11.23935</ogr:left>
|
||||
<ogr:top>-0.11331</ogr:top>
|
||||
<ogr:right>14.23935</ogr:right>
|
||||
<ogr:bottom>-3.11331</ogr:bottom>
|
||||
<ogr:id>19</ogr:id>
|
||||
<ogr:color_id>2</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.6">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>11.2393496420048,-3.11330548926014 14.2393496420048,-3.11330548926014 14.2393496420048,-6.11330548926014 11.2393496420048,-6.11330548926014 11.2393496420048,-3.11330548926014</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>11.23935</ogr:left>
|
||||
<ogr:top>-3.11331</ogr:top>
|
||||
<ogr:right>14.23935</ogr:right>
|
||||
<ogr:bottom>-6.11331</ogr:bottom>
|
||||
<ogr:id>20</ogr:id>
|
||||
<ogr:color_id>5</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.7">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.23934964200477,5.88669451073986 5.23934964200477,5.88669451073986 5.23934964200477,2.88669451073986 2.23934964200477,2.88669451073986 2.23934964200477,-0.113305489260142 -0.760650357995228,-0.113305489260142 -0.760650357995228,2.88669451073986 -0.760650357995228,5.88669451073986 2.23934964200477,5.88669451073986</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>2.23935</ogr:left>
|
||||
<ogr:top>5.88669</ogr:top>
|
||||
<ogr:right>5.23935</ogr:right>
|
||||
<ogr:bottom>2.88669</ogr:bottom>
|
||||
<ogr:id>5</ogr:id>
|
||||
<ogr:color_id>3</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.8">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5.23934964200477,2.88669451073986 8.23934964200477,2.88669451073986 11.2393496420048,2.88669451073986 11.2393496420048,-0.113305489260142 11.2393496420048,-3.11330548926014 8.23934964200477,-3.11330548926014 8.23934964200477,-0.113305489260142 5.23934964200477,-0.113305489260142 5.23934964200477,2.88669451073986</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>5.23935</ogr:left>
|
||||
<ogr:top>2.88669</ogr:top>
|
||||
<ogr:right>8.23935</ogr:right>
|
||||
<ogr:id>10</ogr:id>
|
||||
<ogr:color_id>1</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.9">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.23934964200477,2.88669451073986 5.23934964200477,2.88669451073986 5.23934964200477,-0.113305489260142 5.23934964200477,-3.11330548926014 5.23934964200477,-6.11330548926014 2.23934964200477,-6.11330548926014 2.23934964200477,-3.11330548926014 2.23934964200477,-0.113305489260142 2.23934964200477,2.88669451073986</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>2.23935</ogr:left>
|
||||
<ogr:top>2.88669</ogr:top>
|
||||
<ogr:right>5.23935</ogr:right>
|
||||
<ogr:id>6</ogr:id>
|
||||
<ogr:color_id>2</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:topocolor_polys fid="adjacent_polys.10">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5.23934964200477,5.88669451073986 8.23934964200477,5.88669451073986 11.2393496420048,5.88669451073986 14.2393496420048,5.88669451073986 14.2393496420048,2.88669451073986 14.2393496420048,-0.113305489260142 11.2393496420048,-0.113305489260142 11.2393496420048,2.88669451073986 8.23934964200477,2.88669451073986 5.23934964200477,2.88669451073986 5.23934964200477,5.88669451073986</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:left>5.23935</ogr:left>
|
||||
<ogr:top>5.88669</ogr:top>
|
||||
<ogr:right>8.23935</ogr:right>
|
||||
<ogr:bottom>2.88669</ogr:bottom>
|
||||
<ogr:id>9</ogr:id>
|
||||
<ogr:color_id>4</ogr:color_id>
|
||||
</ogr:topocolor_polys>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
@ -1148,7 +1148,9 @@ tests:
|
||||
Z_FACTOR: 1.0
|
||||
results:
|
||||
OUTPUT:
|
||||
hash: 762865ee485a6736d188402aa10e6fd38a812a9e45a7dd2d4885a63a
|
||||
hash:
|
||||
- 762865ee485a6736d188402aa10e6fd38a812a9e45a7dd2d4885a63a
|
||||
- f6a8e64647ae93a94f2a4945add8986526a7a07bc85849f3690d15b2
|
||||
type: rasterhash
|
||||
|
||||
- algorithm: qgis:slope
|
||||
@ -1160,7 +1162,9 @@ tests:
|
||||
Z_FACTOR: 1.0
|
||||
results:
|
||||
OUTPUT:
|
||||
hash: 151ea76a21b286c16567eb6b4b692925a84145b65561a0017effb1a1
|
||||
hash:
|
||||
- 151ea76a21b286c16567eb6b4b692925a84145b65561a0017effb1a1
|
||||
- 177475642c57428b395bc0a1e7e86fc1cfd4d86ffc19f31ff8bc964d
|
||||
type: rasterhash
|
||||
|
||||
- algorithm: qgis:ruggednessindex
|
||||
@ -1186,7 +1190,9 @@ tests:
|
||||
Z_FACTOR: 1.0
|
||||
results:
|
||||
OUTPUT:
|
||||
hash: 58365b3715b925d6286e7f082ebd9c2a20f09fa1c922176d3f238002
|
||||
hash:
|
||||
- 58365b3715b925d6286e7f082ebd9c2a20f09fa1c922176d3f238002
|
||||
- 75cca4c1a870a1e21185a2d85b33b6d9958a69fc6ebb04e4d6ceb8a3
|
||||
type: rasterhash
|
||||
|
||||
# - algorithm: qgis:relief
|
||||
@ -1795,21 +1801,21 @@ tests:
|
||||
name: expected/dropped_geometry.csv
|
||||
type: vector
|
||||
|
||||
# - algorithm: qgis:creategridlines
|
||||
# name: Create grid (lines)
|
||||
# params:
|
||||
# CRS: EPSG:4326
|
||||
# EXTENT: -1,11.2,-4,6.5
|
||||
# HSPACING: 5.0
|
||||
# VSPACING: 3.0
|
||||
# results:
|
||||
# OUTPUT:
|
||||
# name: expected/grid_lines.gml
|
||||
# type: vector
|
||||
# compare:
|
||||
# geometry:
|
||||
# precision: 7
|
||||
#
|
||||
- algorithm: qgis:creategridlines
|
||||
name: Create grid (lines)
|
||||
params:
|
||||
CRS: EPSG:4326
|
||||
EXTENT: -1,11.2,-4,6.5
|
||||
HSPACING: 5.0
|
||||
VSPACING: 3.0
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/grid_lines.gml
|
||||
type: vector
|
||||
compare:
|
||||
geometry:
|
||||
precision: 7
|
||||
|
||||
- algorithm: qgis:creategridpolygon
|
||||
name: Create grid (rectangles)
|
||||
params:
|
||||
@ -1858,20 +1864,20 @@ tests:
|
||||
geometry:
|
||||
precision: 7
|
||||
|
||||
# - algorithm: qgis:creategridlines
|
||||
# name: Create grid (lines with overlay)
|
||||
# params:
|
||||
# CRS: EPSG:4326
|
||||
# EXTENT: -1,11.2,-4,6.5
|
||||
# HOVERLAY: 2.0
|
||||
# HSPACING: 5.0
|
||||
# VOVERLAY: 1.0
|
||||
# VSPACING: 3.0
|
||||
# results:
|
||||
# OUTPUT:
|
||||
# name: expected/grid_lines_overlay.gml
|
||||
# type: vector
|
||||
#
|
||||
- algorithm: qgis:creategridlines
|
||||
name: Create grid (lines with overlay)
|
||||
params:
|
||||
CRS: EPSG:4326
|
||||
EXTENT: -1,11.2,-4,6.5
|
||||
HOVERLAY: 2.0
|
||||
HSPACING: 5.0
|
||||
VOVERLAY: 1.0
|
||||
VSPACING: 3.0
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/grid_lines_overlay.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:creategridpolygon
|
||||
name: Create grid (rectangle with overlay)
|
||||
params:
|
||||
@ -2158,21 +2164,122 @@ tests:
|
||||
name: expected/lines_to_polygon.gml
|
||||
type: vector
|
||||
|
||||
# - algorithm: qgis:joinattributestable
|
||||
# name: join the attribute table by common field
|
||||
# params:
|
||||
# INPUT_LAYER:
|
||||
# name: points.gml
|
||||
# type: vector
|
||||
# INPUT_LAYER_2:
|
||||
# name: table.dbf
|
||||
# type: table
|
||||
# TABLE_FIELD: id
|
||||
# TABLE_FIELD_2: ID
|
||||
# results:
|
||||
# OUTPUT_LAYER:
|
||||
# name: expected/join_attribute_table.gml
|
||||
# type: vector
|
||||
- algorithm: qgis:snappointstogrid
|
||||
name: Gridify polys
|
||||
params:
|
||||
INPUT:
|
||||
name: polys.gml
|
||||
type: vector
|
||||
HSPACING: 2
|
||||
VSPACING: 2
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/gridify_polys.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:snappointstogrid
|
||||
name: Gridify lines
|
||||
params:
|
||||
INPUT:
|
||||
name: lines.gml
|
||||
type: vector
|
||||
HSPACING: 2
|
||||
VSPACING: 2
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/gridify_lines.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:distancetonearesthubpoints
|
||||
name: Hub distance points
|
||||
params:
|
||||
INPUT:
|
||||
name: points.gml
|
||||
type: vector
|
||||
HUBS:
|
||||
name: custom/hub_points.gml
|
||||
type: vector
|
||||
FIELD: name
|
||||
UNIT: 0
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/hub_distance_points.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:distancetonearesthublinetohub
|
||||
name: Hub distance lines
|
||||
params:
|
||||
INPUT:
|
||||
name: points.gml
|
||||
type: vector
|
||||
HUBS:
|
||||
name: custom/hub_points.gml
|
||||
type: vector
|
||||
FIELD: name
|
||||
UNIT: 0
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/hub_distance_lines.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:hublines
|
||||
name: Hub lines
|
||||
params:
|
||||
HUBS:
|
||||
name: points.gml
|
||||
type: vector
|
||||
SPOKES:
|
||||
name: custom/spoke_points.gml
|
||||
type: vector
|
||||
HUB_FIELD: id
|
||||
SPOKE_FIELD: id
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/hub_lines.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:pointstopath
|
||||
name: Points to path (non grouped)
|
||||
params:
|
||||
INPUT:
|
||||
name: points.gml
|
||||
type: vector
|
||||
ORDER_FIELD: id
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/points_to_path.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:pointstopath
|
||||
name: Points to path (grouped)
|
||||
params:
|
||||
INPUT:
|
||||
name: points.gml
|
||||
type: vector
|
||||
ORDER_FIELD: id
|
||||
GROUP_FIELD: id2
|
||||
results:
|
||||
OUTPUT:
|
||||
name:
|
||||
- expected/points_to_path_grouped.gml
|
||||
- expected/points_to_path_grouped2.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:joinattributestable
|
||||
name: join the attribute table by common field
|
||||
params:
|
||||
INPUT:
|
||||
name: points.gml
|
||||
type: vector
|
||||
INPUT_2:
|
||||
name: table.dbf
|
||||
type: table
|
||||
FIELD: id
|
||||
FIELD_2: ID
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/join_attribute_table.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:convexhull
|
||||
name: Simple convex hull
|
||||
@ -2382,6 +2489,23 @@ tests:
|
||||
name: expected/single_to_multi.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:statisticsbycategories
|
||||
name: stats by category
|
||||
params:
|
||||
VALUES_FIELD_NAME: id
|
||||
CATEGORIES_FIELD_NAME: id2
|
||||
INPUT:
|
||||
name: points.gml
|
||||
type: vector
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/stats_by_category.gml
|
||||
type: vector
|
||||
pk: id2
|
||||
compare:
|
||||
fields:
|
||||
fid: skip
|
||||
|
||||
# - algorithm: qgis:zonalstatistics
|
||||
# name: simple zonal statistics
|
||||
# params:
|
||||
@ -2499,32 +2623,35 @@ tests:
|
||||
name: expected/polygon_from_extent.gml
|
||||
type: vector
|
||||
|
||||
# - algorithm: qgis:topologicalcoloring
|
||||
# name: Topological coloring
|
||||
# params:
|
||||
# INPUT_LAYER:
|
||||
# name: custom/adjacent_polys.gml
|
||||
# type: vector
|
||||
# MIN_COLORS: 4
|
||||
# results:
|
||||
# OUTPUT_LAYER:
|
||||
# name: expected/topocolor_polys.gml
|
||||
# type: vector
|
||||
#
|
||||
# - algorithm: qgis:topologicalcoloring
|
||||
# name: Topological coloring w/ min distance
|
||||
# params:
|
||||
# BALANCE: '0'
|
||||
# INPUT_LAYER:
|
||||
# name: custom/adjacent_polys.gml
|
||||
# type: vector
|
||||
# MIN_COLORS: 4
|
||||
# MIN_DISTANCE: 4.0
|
||||
# results:
|
||||
# OUTPUT_LAYER:
|
||||
# name: expected/topocolor_polys_min_dist.gml
|
||||
# type: vector
|
||||
#
|
||||
- algorithm: qgis:topologicalcoloring
|
||||
name: Topological coloring
|
||||
params:
|
||||
BALANCE: 0
|
||||
INPUT:
|
||||
name: custom/adjacent_polys.gml
|
||||
type: vector
|
||||
MIN_COLORS: 4
|
||||
results:
|
||||
OUTPUT:
|
||||
type: vector
|
||||
name:
|
||||
- expected/topocolor_polys.gml
|
||||
- expected/topocolor_polys2.gml
|
||||
|
||||
- algorithm: qgis:topologicalcoloring
|
||||
name: Topological coloring w/ min distance
|
||||
params:
|
||||
BALANCE: 0
|
||||
INPUT:
|
||||
name: custom/adjacent_polys.gml
|
||||
type: vector
|
||||
MIN_COLORS: 4
|
||||
MIN_DISTANCE: 4.0
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/topocolor_polys_min_dist.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:regularpoints
|
||||
name: Regular point with standard extent
|
||||
params:
|
||||
@ -2586,21 +2713,21 @@ tests:
|
||||
# OUTPUT_LAYER:
|
||||
# name: expected/buffer_ovals.gml
|
||||
# type: vector
|
||||
#
|
||||
# - algorithm: qgis:creategridlines
|
||||
# name: Lines grid 0.1 degree spacing
|
||||
# params:
|
||||
# CRS: EPSG:4326
|
||||
# EXTENT: -0.10453905405405395,8.808021567567568,-2.5010055337837844,4.058021763513514
|
||||
# HOVERLAY: 0.0
|
||||
# HSPACING: 0.1
|
||||
# VOVERLAY: 0.0
|
||||
# VSPACING: 0.1
|
||||
# results:
|
||||
# OUTPUT:
|
||||
# name: expected/create_grid_lines.gml
|
||||
# type: vector
|
||||
#
|
||||
|
||||
- algorithm: qgis:creategridlines
|
||||
name: Lines grid 0.1 degree spacing
|
||||
params:
|
||||
CRS: EPSG:4326
|
||||
EXTENT: -0.10453905405405395,8.808021567567568,-2.5010055337837844,4.058021763513514
|
||||
HOVERLAY: 0.0
|
||||
HSPACING: 0.1
|
||||
VOVERLAY: 0.0
|
||||
VSPACING: 0.1
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/create_grid_lines.gml
|
||||
type: vector
|
||||
|
||||
# - algorithm: qgis:convertgeometrytype
|
||||
# name: polygon to centroid
|
||||
# params:
|
||||
|
@ -54,6 +54,29 @@ class TestCase(_TestCase):
|
||||
:keyword compare: A map of comparison options. e.g.
|
||||
{ fields: { a: skip, b: { precision: 2 }, geometry: { precision: 5 } }
|
||||
{ fields: { __all__: cast( str ) } }
|
||||
:keyword pk: "Primary key" type field - used to match features
|
||||
from the expected table to their corresponding features in the result table. If not specified
|
||||
features are compared by their order in the layer (e.g. first feature compared with first feature,
|
||||
etc)
|
||||
"""
|
||||
self.checkLayersEqual(layer_expected, layer_result, True, **kwargs)
|
||||
|
||||
def checkLayersEqual(self, layer_expected, layer_result, use_asserts=False, **kwargs):
|
||||
"""
|
||||
:param layer_expected: The first layer to compare
|
||||
:param layer_result: The second layer to compare
|
||||
:param use_asserts: If true, asserts are used to test conditions, if false, asserts
|
||||
are not used and the function will only return False if the test fails
|
||||
:param request: Optional, A feature request. This can be used to specify
|
||||
an order by clause to make sure features are compared in
|
||||
a given sequence if they don't match by default.
|
||||
:keyword compare: A map of comparison options. e.g.
|
||||
{ fields: { a: skip, b: { precision: 2 }, geometry: { precision: 5 } }
|
||||
{ fields: { __all__: cast( str ) } }
|
||||
:keyword pk: "Primary key" type field - used to match features
|
||||
from the expected table to their corresponding features in the result table. If not specified
|
||||
features are compared by their order in the layer (e.g. first feature compared with first feature,
|
||||
etc)
|
||||
"""
|
||||
|
||||
try:
|
||||
@ -67,18 +90,30 @@ class TestCase(_TestCase):
|
||||
compare = {}
|
||||
|
||||
# Compare CRS
|
||||
_TestCase.assertEqual(self, layer_expected.dataProvider().crs().authid(), layer_result.dataProvider().crs().authid())
|
||||
if use_asserts:
|
||||
_TestCase.assertEqual(self, layer_expected.dataProvider().crs().authid(), layer_result.dataProvider().crs().authid())
|
||||
elif not layer_expected.dataProvider().crs().authid() == layer_result.dataProvider().crs().authid():
|
||||
return False
|
||||
|
||||
# Compare features
|
||||
_TestCase.assertEqual(self, layer_expected.featureCount(), layer_result.featureCount())
|
||||
if use_asserts:
|
||||
_TestCase.assertEqual(self, layer_expected.featureCount(), layer_result.featureCount())
|
||||
elif layer_expected.featureCount() != layer_result.featureCount():
|
||||
return False
|
||||
|
||||
try:
|
||||
precision = compare['geometry']['precision']
|
||||
except KeyError:
|
||||
precision = 14
|
||||
|
||||
expected_features = sorted(layer_expected.getFeatures(request), key=lambda f: f.id())
|
||||
result_features = sorted(layer_result.getFeatures(request), key=lambda f: f.id())
|
||||
def sort_by_pk_or_fid(f):
|
||||
if 'pk' in kwargs and kwargs['pk'] is not None:
|
||||
return f[kwargs['pk']]
|
||||
else:
|
||||
return f.id()
|
||||
|
||||
expected_features = sorted(layer_expected.getFeatures(request), key=sort_by_pk_or_fid)
|
||||
result_features = sorted(layer_result.getFeatures(request), key=sort_by_pk_or_fid)
|
||||
|
||||
for feats in zip(expected_features, result_features):
|
||||
if feats[0].hasGeometry():
|
||||
@ -89,17 +124,20 @@ class TestCase(_TestCase):
|
||||
geom1 = feats[1].geometry().geometry().asWkt(precision)
|
||||
else:
|
||||
geom1 = None
|
||||
_TestCase.assertEqual(
|
||||
self,
|
||||
geom0,
|
||||
geom1,
|
||||
'Features {}/{} differ in geometry: \n\n {}\n\n vs \n\n {}'.format(
|
||||
feats[0].id(),
|
||||
feats[1].id(),
|
||||
if use_asserts:
|
||||
_TestCase.assertEqual(
|
||||
self,
|
||||
geom0,
|
||||
geom1
|
||||
geom1,
|
||||
'Features {}/{} differ in geometry: \n\n {}\n\n vs \n\n {}'.format(
|
||||
feats[0].id(),
|
||||
feats[1].id(),
|
||||
geom0,
|
||||
geom1
|
||||
)
|
||||
)
|
||||
)
|
||||
elif geom0 != geom1:
|
||||
return False
|
||||
|
||||
for attr_expected, field_expected in zip(feats[0].attributes(), layer_expected.fields().toList()):
|
||||
try:
|
||||
@ -134,21 +172,26 @@ class TestCase(_TestCase):
|
||||
attr_expected = round(attr_expected, cmp['precision'])
|
||||
attr_result = round(attr_result, cmp['precision'])
|
||||
|
||||
_TestCase.assertEqual(
|
||||
self,
|
||||
attr_expected,
|
||||
attr_result,
|
||||
'Features {}/{} differ in attributes\n\n * Field1: {} ({})\n * Field2: {} ({})\n\n * {} != {}'.format(
|
||||
feats[0].id(),
|
||||
feats[1].id(),
|
||||
field_expected.name(),
|
||||
field_expected.typeName(),
|
||||
field_result.name(),
|
||||
field_result.typeName(),
|
||||
repr(attr_expected),
|
||||
repr(attr_result)
|
||||
if use_asserts:
|
||||
_TestCase.assertEqual(
|
||||
self,
|
||||
attr_expected,
|
||||
attr_result,
|
||||
'Features {}/{} differ in attributes\n\n * Field1: {} ({})\n * Field2: {} ({})\n\n * {} != {}'.format(
|
||||
feats[0].id(),
|
||||
feats[1].id(),
|
||||
field_expected.name(),
|
||||
field_expected.typeName(),
|
||||
field_result.name(),
|
||||
field_result.typeName(),
|
||||
repr(attr_expected),
|
||||
repr(attr_result)
|
||||
)
|
||||
)
|
||||
)
|
||||
elif attr_expected != attr_result:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def assertFilesEqual(self, filepath_expected, filepath_result):
|
||||
with open(filepath_expected, 'r') as file_expected:
|
||||
|
@ -147,6 +147,7 @@ void QgsApplication::init( QString profileFolder )
|
||||
qRegisterMetaType<QgsProcessingFeatureSourceDefinition>( "QgsProcessingFeatureSourceDefinition" );
|
||||
qRegisterMetaType<QgsProcessingOutputLayerDefinition>( "QgsProcessingOutputLayerDefinition" );
|
||||
qRegisterMetaType<QgsUnitTypes::LayoutUnit>( "QgsUnitTypes::LayoutUnit" );
|
||||
qRegisterMetaType<QgsFeatureIds>( "QgsFeatureIds" );
|
||||
|
||||
QString prefixPath( getenv( "QGIS_PREFIX_PATH" ) ? getenv( "QGIS_PREFIX_PATH" ) : applicationDirPath() );
|
||||
// QgsDebugMsg( QString( "prefixPath(): %1" ).arg( prefixPath ) );
|
||||
|
Loading…
x
Reference in New Issue
Block a user