Skip to content
Permalink
Browse files

[processing] restore Random points in layer bounds

  • Loading branch information
alexbruy committed Jul 21, 2017
1 parent eb9f45c commit ae2e32b36e24a6a0a02c1efccb072bfa579e644d
@@ -85,6 +85,7 @@
from .RandomExtract import RandomExtract
from .RandomExtractWithinSubsets import RandomExtractWithinSubsets
from .RandomPointsExtent import RandomPointsExtent
from .RandomPointsLayer import RandomPointsLayer
from .RegularPoints import RegularPoints
from .ReverseLineDirection import ReverseLineDirection
from .Ruggedness import Ruggedness
@@ -142,7 +143,6 @@
# from .PointsDisplacement import PointsDisplacement
# from .PointsFromPolygons import PointsFromPolygons
# from .PointsFromLines import PointsFromLines
# from .RandomPointsLayer import RandomPointsLayer
# from .RandomPointsPolygonsFixed import RandomPointsPolygonsFixed
# from .RandomPointsPolygonsVariable import RandomPointsPolygonsVariable
# from .RandomPointsAlongLines import RandomPointsAlongLines
@@ -273,6 +273,7 @@ def getAlgs(self):
RandomExtract(),
RandomExtractWithinSubsets(),
RandomPointsExtent(),
RandomPointsLayer(),
RegularPoints(),
ReverseLineDirection(),
Ruggedness(),
@@ -30,25 +30,37 @@

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

from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterNumber
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector
from processing.tools import vector

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


class RandomPointsLayer(QgisAlgorithm):

VECTOR = 'VECTOR'
POINT_NUMBER = 'POINT_NUMBER'
INPUT = 'INPUT'
POINTS_NUMBER = 'POINTS_NUMBER'
MIN_DISTANCE = 'MIN_DISTANCE'
ADD_Z = 'ADD_Z'
ADD_M = 'ADD_M'
OUTPUT = 'OUTPUT'

def icon(self):
@@ -61,13 +73,31 @@ def __init__(self):
super().__init__()

def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(self.VECTOR,
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_POLYGON]))
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.addOutput(OutputVector(self.OUTPUT, self.tr('Random points'), datatype=[dataobjects.TYPE_VECTOR_POINT]))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer'),
[QgsProcessing.TypeVectorPolygon]))
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))
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 'randompointsinlayerbounds'
@@ -76,16 +106,26 @@ def displayName(self):
return self.tr('Random points in layer bounds')

def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.VECTOR), context)
pointCount = int(self.getParameterValue(self.POINT_NUMBER))
minDistance = float(self.getParameterValue(self.MIN_DISTANCE))
source = self.parameterAsSource(parameters, self.INPUT, context)
pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context)
minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context)
addZ = self.parameterAsBool(parameters, self.ADD_Z, context)
addM = self.parameterAsBool(parameters, self.ADD_M, context)

bbox = layer.extent()
idxLayer = QgsProcessingUtils.createSpatialIndex(layer, context)
bbox = source.sourceExtent()
sourceIndex = QgsSpatialIndex(source, feedback)

fields = QgsFields()
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Point, layer.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, source.sourceCrs())

nPoints = 0
nIterations = 0
@@ -98,32 +138,43 @@ def processAlgorithm(self, parameters, context, feedback):
random.seed()

while nIterations < maxIterations and nPoints < pointCount:
if feedback.isCanceled():
break

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

pnt = QgsPointXY(rx, ry)
geom = QgsGeometry.fromPoint(pnt)
ids = idxLayer.intersects(geom.buffer(5, 5).boundingBox())
pnt = QgsPoint(rx, ry)
p = QgsPointXY(rx, ry)
if addZ:
pnt.addZValue(0.0)
if addM:
pnt.addMValue(0.0)
geom = QgsGeometry(pnt)
ids = sourceIndex.intersects(geom.buffer(5, 5).boundingBox())
if len(ids) > 0 and \
vector.checkMinDistance(pnt, index, minDistance, points):
vector.checkMinDistance(p, index, minDistance, points):
request = QgsFeatureRequest().setFilterFids(ids).setSubsetOfAttributes([])
for f in layer.getFeatures(request):
for f in source.getFeatures(request):
if feedback.isCanceled():
break

tmpGeom = f.geometry()
if geom.within(tmpGeom):
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 ae2e32b

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