Skip to content
Permalink
Browse files

[processing] port Random points within extent

  • Loading branch information
alexbruy committed Jul 21, 2017
1 parent 2723f4f commit eb9f45cbb09ce77b03fe210eaf505fc9121ff628
@@ -84,6 +84,7 @@
from .PostGISExecuteSQL import PostGISExecuteSQL
from .RandomExtract import RandomExtract
from .RandomExtractWithinSubsets import RandomExtractWithinSubsets
from .RandomPointsExtent import RandomPointsExtent
from .RegularPoints import RegularPoints
from .ReverseLineDirection import ReverseLineDirection
from .Ruggedness import Ruggedness
@@ -141,7 +142,6 @@
# from .PointsDisplacement import PointsDisplacement
# from .PointsFromPolygons import PointsFromPolygons
# from .PointsFromLines import PointsFromLines
# from .RandomPointsExtent import RandomPointsExtent
# from .RandomPointsLayer import RandomPointsLayer
# from .RandomPointsPolygonsFixed import RandomPointsPolygonsFixed
# from .RandomPointsPolygonsVariable import RandomPointsPolygonsVariable
@@ -272,6 +272,7 @@ def getAlgs(self):
PostGISExecuteSQL(),
RandomExtract(),
RandomExtractWithinSubsets(),
RandomPointsExtent(),
RegularPoints(),
ReverseLineDirection(),
Ruggedness(),
@@ -31,29 +31,39 @@

from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtCore import QVariant
from qgis.core import (QgsGeometry, QgsFeatureSink, QgsRectangle, QgsFeature, QgsFields, QgsWkbTypes,
QgsField, QgsSpatialIndex, QgsPointXY,
QgsCoordinateReferenceSystem,
QgsMessageLog,
QgsProcessingUtils)
from qgis.core import (QgsField,
QgsFeatureSink,
QgsFeature,
QgsFields,
QgsGeometry,
QgsPoint,
QgsPointXY,
QgsWkbTypes,
QgsSpatialIndex,
QgsProcessing,
QgsProcessingException,
QgsProcessingParameterExtent,
QgsProcessingParameterNumber,
QgsProcessingParameterCrs,
QgsProcessingParameterBoolean,
QgsProcessingParameterFeatureSink,
QgsProcessingParameterDefinition)

from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
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 vector, dataobjects
from processing.tools import vector

pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]


class RandomPointsExtent(QgisAlgorithm):

EXTENT = 'EXTENT'
POINT_NUMBER = 'POINT_NUMBER'
POINTS_NUMBER = 'POINTS_NUMBER'
MIN_DISTANCE = 'MIN_DISTANCE'
TARGET_CRS = 'TARGET_CRS'
ADD_Z = 'ADD_Z'
ADD_M = 'ADD_M'
OUTPUT = 'OUTPUT'
CRS = 'CRS'

def icon(self):
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'random_points.png'))
@@ -65,15 +75,33 @@ def __init__(self):
super().__init__()

def initAlgorithm(self, config=None):
self.addParameter(ParameterExtent(self.EXTENT,
self.tr('Input extent'), optional=False))
self.addParameter(ParameterNumber(self.POINT_NUMBER,
self.tr('Points number'), 1, None, 1))
self.addParameter(ParameterNumber(self.MIN_DISTANCE,
self.tr('Minimum distance'), 0.0, None, 0.0))
self.addParameter(ParameterCrs(self.CRS,
self.tr('Output layer CRS'), 'ProjectCrs'))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Random points'), datatype=[dataobjects.TYPE_VECTOR_POINT]))
self.addParameter(QgsProcessingParameterExtent(self.EXTENT, self.tr('Input extent')))
self.addParameter(QgsProcessingParameterNumber(self.POINTS_NUMBER,
self.tr('Number of points'),
QgsProcessingParameterNumber.Integer,
1, False, 1, 1000000000))
self.addParameter(QgsProcessingParameterNumber(self.MIN_DISTANCE,
self.tr('Minimum distance between points'),
QgsProcessingParameterNumber.Double,
0, False, 0, 1000000000))
self.addParameter(QgsProcessingParameterCrs(self.TARGET_CRS,
self.tr('Target CRS'),
'ProjectCrs'))

params = []
params.append(QgsProcessingParameterBoolean(self.ADD_Z,
self.tr('Add Z coordinate'),
False))
params.append(QgsProcessingParameterBoolean(self.ADD_M,
self.tr('Add M coordinate'),
False))
for p in params:
p.setFlags(p.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
self.addParameter(p)

self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT,
self.tr('Random points'),
type=QgsProcessing.TypeVectorPoint))

def name(self):
return 'randompointsinextent'
@@ -82,24 +110,26 @@ def displayName(self):
return self.tr('Random points in extent')

def processAlgorithm(self, parameters, context, feedback):
pointCount = int(self.getParameterValue(self.POINT_NUMBER))
minDistance = float(self.getParameterValue(self.MIN_DISTANCE))
extent = str(self.getParameterValue(self.EXTENT)).split(',')
bbox = self.parameterAsExtent(parameters, self.EXTENT, context)
pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context)
minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context)
crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context)
addZ = self.parameterAsBool(parameters, self.ADD_Z, context)
addM = self.parameterAsBool(parameters, self.ADD_M, context)

crsId = self.getParameterValue(self.CRS)
crs = QgsCoordinateReferenceSystem()
crs.createFromUserInput(crsId)

xMin = float(extent[0])
xMax = float(extent[1])
yMin = float(extent[2])
yMax = float(extent[3])
extent = QgsGeometry().fromRect(
QgsRectangle(xMin, yMin, xMax, yMax))
extent = QgsGeometry().fromRect(bbox)

fields = QgsFields()
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Point, crs, context)

wkbType = QgsWkbTypes.Point
if addZ:
wkbType = QgsWkbTypes.addZ(wkbType)
if addM:
wkbType = QgsWkbTypes.addM(wkbType)

(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, wkbType, crs)

nPoints = 0
nIterations = 0
@@ -112,27 +142,35 @@ def processAlgorithm(self, parameters, context, feedback):
random.seed()

while nIterations < maxIterations and nPoints < pointCount:
rx = xMin + (xMax - xMin) * random.random()
ry = yMin + (yMax - yMin) * random.random()

pnt = QgsPointXY(rx, ry)
geom = QgsGeometry.fromPoint(pnt)
if feedback.isCanceled():
break

rx = bbox.xMinimum() + bbox.width() * random.random()
ry = bbox.yMinimum() + bbox.height() * random.random()

pnt = QgsPoint(rx, ry)
p = QgsPointXY(rx, ry)
if addZ:
pnt.addZValue(0.0)
if addM:
pnt.addMValue(0.0)
geom = QgsGeometry(pnt)
if geom.within(extent) and \
vector.checkMinDistance(pnt, index, minDistance, points):
vector.checkMinDistance(p, index, minDistance, points):
f = QgsFeature(nPoints)
f.initAttributes(1)
f.setFields(fields)
f.setAttribute('id', nPoints)
f.setGeometry(geom)
writer.addFeature(f, QgsFeatureSink.FastInsert)
sink.addFeature(f, QgsFeatureSink.FastInsert)
index.insertFeature(f)
points[nPoints] = pnt
points[nPoints] = p
nPoints += 1
feedback.setProgress(int(nPoints * total))
nIterations += 1

if nPoints < pointCount:
QgsMessageLog.logMessage(self.tr('Can not generate requested number of random points. '
'Maximum number of attempts exceeded.'), self.tr('Processing'), QgsMessageLog.INFO)
feedback.pushInfo(self.tr('Could not generate requested number of random points. '
'Maximum number of attempts exceeded.'))

del writer
return {self.OUTPUT: dest_id}

0 comments on commit eb9f45c

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