mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-19 00:04:52 -04:00
[processing] restore Random points in layer bounds
This commit is contained in:
parent
eb9f45cbb0
commit
ae2e32b36e
@ -85,6 +85,7 @@ from .PostGISExecuteSQL import PostGISExecuteSQL
|
|||||||
from .RandomExtract import RandomExtract
|
from .RandomExtract import RandomExtract
|
||||||
from .RandomExtractWithinSubsets import RandomExtractWithinSubsets
|
from .RandomExtractWithinSubsets import RandomExtractWithinSubsets
|
||||||
from .RandomPointsExtent import RandomPointsExtent
|
from .RandomPointsExtent import RandomPointsExtent
|
||||||
|
from .RandomPointsLayer import RandomPointsLayer
|
||||||
from .RegularPoints import RegularPoints
|
from .RegularPoints import RegularPoints
|
||||||
from .ReverseLineDirection import ReverseLineDirection
|
from .ReverseLineDirection import ReverseLineDirection
|
||||||
from .Ruggedness import Ruggedness
|
from .Ruggedness import Ruggedness
|
||||||
@ -142,7 +143,6 @@ from .ZonalStatistics import ZonalStatistics
|
|||||||
# from .PointsDisplacement import PointsDisplacement
|
# from .PointsDisplacement import PointsDisplacement
|
||||||
# from .PointsFromPolygons import PointsFromPolygons
|
# from .PointsFromPolygons import PointsFromPolygons
|
||||||
# from .PointsFromLines import PointsFromLines
|
# from .PointsFromLines import PointsFromLines
|
||||||
# from .RandomPointsLayer import RandomPointsLayer
|
|
||||||
# from .RandomPointsPolygonsFixed import RandomPointsPolygonsFixed
|
# from .RandomPointsPolygonsFixed import RandomPointsPolygonsFixed
|
||||||
# from .RandomPointsPolygonsVariable import RandomPointsPolygonsVariable
|
# from .RandomPointsPolygonsVariable import RandomPointsPolygonsVariable
|
||||||
# from .RandomPointsAlongLines import RandomPointsAlongLines
|
# from .RandomPointsAlongLines import RandomPointsAlongLines
|
||||||
@ -273,6 +273,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
|||||||
RandomExtract(),
|
RandomExtract(),
|
||||||
RandomExtractWithinSubsets(),
|
RandomExtractWithinSubsets(),
|
||||||
RandomPointsExtent(),
|
RandomPointsExtent(),
|
||||||
|
RandomPointsLayer(),
|
||||||
RegularPoints(),
|
RegularPoints(),
|
||||||
ReverseLineDirection(),
|
ReverseLineDirection(),
|
||||||
Ruggedness(),
|
Ruggedness(),
|
||||||
|
@ -30,25 +30,37 @@ import random
|
|||||||
|
|
||||||
from qgis.PyQt.QtGui import QIcon
|
from qgis.PyQt.QtGui import QIcon
|
||||||
from qgis.PyQt.QtCore import QVariant
|
from qgis.PyQt.QtCore import QVariant
|
||||||
from qgis.core import (QgsGeometry, QgsFeatureSink, QgsFields, QgsField, QgsSpatialIndex, QgsWkbTypes,
|
from qgis.core import (QgsField,
|
||||||
QgsPointXY, QgsFeature, QgsFeatureRequest,
|
QgsFeatureSink,
|
||||||
QgsMessageLog,
|
QgsFeature,
|
||||||
QgsProcessingUtils)
|
QgsFields,
|
||||||
|
QgsGeometry,
|
||||||
|
QgsPoint,
|
||||||
|
QgsPointXY,
|
||||||
|
QgsWkbTypes,
|
||||||
|
QgsSpatialIndex,
|
||||||
|
QgsFeatureRequest,
|
||||||
|
QgsProcessing,
|
||||||
|
QgsProcessingException,
|
||||||
|
QgsProcessingParameterNumber,
|
||||||
|
QgsProcessingParameterBoolean,
|
||||||
|
QgsProcessingParameterFeatureSource,
|
||||||
|
QgsProcessingParameterFeatureSink,
|
||||||
|
QgsProcessingParameterDefinition)
|
||||||
|
|
||||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||||
from processing.core.parameters import ParameterVector
|
from processing.tools import vector
|
||||||
from processing.core.parameters import ParameterNumber
|
|
||||||
from processing.core.outputs import OutputVector
|
|
||||||
from processing.tools import dataobjects, vector
|
|
||||||
|
|
||||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||||
|
|
||||||
|
|
||||||
class RandomPointsLayer(QgisAlgorithm):
|
class RandomPointsLayer(QgisAlgorithm):
|
||||||
|
|
||||||
VECTOR = 'VECTOR'
|
INPUT = 'INPUT'
|
||||||
POINT_NUMBER = 'POINT_NUMBER'
|
POINTS_NUMBER = 'POINTS_NUMBER'
|
||||||
MIN_DISTANCE = 'MIN_DISTANCE'
|
MIN_DISTANCE = 'MIN_DISTANCE'
|
||||||
|
ADD_Z = 'ADD_Z'
|
||||||
|
ADD_M = 'ADD_M'
|
||||||
OUTPUT = 'OUTPUT'
|
OUTPUT = 'OUTPUT'
|
||||||
|
|
||||||
def icon(self):
|
def icon(self):
|
||||||
@ -61,13 +73,31 @@ class RandomPointsLayer(QgisAlgorithm):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
def initAlgorithm(self, config=None):
|
def initAlgorithm(self, config=None):
|
||||||
self.addParameter(ParameterVector(self.VECTOR,
|
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
|
||||||
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_POLYGON]))
|
self.tr('Input layer'),
|
||||||
self.addParameter(ParameterNumber(self.POINT_NUMBER,
|
[QgsProcessing.TypeVectorPolygon]))
|
||||||
self.tr('Points number'), 1, None, 1))
|
self.addParameter(QgsProcessingParameterNumber(self.POINTS_NUMBER,
|
||||||
self.addParameter(ParameterNumber(self.MIN_DISTANCE,
|
self.tr('Number of points'),
|
||||||
self.tr('Minimum distance'), 0.0, None, 0.0))
|
QgsProcessingParameterNumber.Integer,
|
||||||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Random points'), datatype=[dataobjects.TYPE_VECTOR_POINT]))
|
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):
|
def name(self):
|
||||||
return 'randompointsinlayerbounds'
|
return 'randompointsinlayerbounds'
|
||||||
@ -76,16 +106,26 @@ class RandomPointsLayer(QgisAlgorithm):
|
|||||||
return self.tr('Random points in layer bounds')
|
return self.tr('Random points in layer bounds')
|
||||||
|
|
||||||
def processAlgorithm(self, parameters, context, feedback):
|
def processAlgorithm(self, parameters, context, feedback):
|
||||||
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.VECTOR), context)
|
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||||
pointCount = int(self.getParameterValue(self.POINT_NUMBER))
|
pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context)
|
||||||
minDistance = float(self.getParameterValue(self.MIN_DISTANCE))
|
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()
|
bbox = source.sourceExtent()
|
||||||
idxLayer = QgsProcessingUtils.createSpatialIndex(layer, context)
|
sourceIndex = QgsSpatialIndex(source, feedback)
|
||||||
|
|
||||||
fields = QgsFields()
|
fields = QgsFields()
|
||||||
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
|
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
|
nPoints = 0
|
||||||
nIterations = 0
|
nIterations = 0
|
||||||
@ -98,16 +138,27 @@ class RandomPointsLayer(QgisAlgorithm):
|
|||||||
random.seed()
|
random.seed()
|
||||||
|
|
||||||
while nIterations < maxIterations and nPoints < pointCount:
|
while nIterations < maxIterations and nPoints < pointCount:
|
||||||
|
if feedback.isCanceled():
|
||||||
|
break
|
||||||
|
|
||||||
rx = bbox.xMinimum() + bbox.width() * random.random()
|
rx = bbox.xMinimum() + bbox.width() * random.random()
|
||||||
ry = bbox.yMinimum() + bbox.height() * random.random()
|
ry = bbox.yMinimum() + bbox.height() * random.random()
|
||||||
|
|
||||||
pnt = QgsPointXY(rx, ry)
|
pnt = QgsPoint(rx, ry)
|
||||||
geom = QgsGeometry.fromPoint(pnt)
|
p = QgsPointXY(rx, ry)
|
||||||
ids = idxLayer.intersects(geom.buffer(5, 5).boundingBox())
|
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 \
|
if len(ids) > 0 and \
|
||||||
vector.checkMinDistance(pnt, index, minDistance, points):
|
vector.checkMinDistance(p, index, minDistance, points):
|
||||||
request = QgsFeatureRequest().setFilterFids(ids).setSubsetOfAttributes([])
|
request = QgsFeatureRequest().setFilterFids(ids).setSubsetOfAttributes([])
|
||||||
for f in layer.getFeatures(request):
|
for f in source.getFeatures(request):
|
||||||
|
if feedback.isCanceled():
|
||||||
|
break
|
||||||
|
|
||||||
tmpGeom = f.geometry()
|
tmpGeom = f.geometry()
|
||||||
if geom.within(tmpGeom):
|
if geom.within(tmpGeom):
|
||||||
f = QgsFeature(nPoints)
|
f = QgsFeature(nPoints)
|
||||||
@ -115,15 +166,15 @@ class RandomPointsLayer(QgisAlgorithm):
|
|||||||
f.setFields(fields)
|
f.setFields(fields)
|
||||||
f.setAttribute('id', nPoints)
|
f.setAttribute('id', nPoints)
|
||||||
f.setGeometry(geom)
|
f.setGeometry(geom)
|
||||||
writer.addFeature(f, QgsFeatureSink.FastInsert)
|
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||||
index.insertFeature(f)
|
index.insertFeature(f)
|
||||||
points[nPoints] = pnt
|
points[nPoints] = p
|
||||||
nPoints += 1
|
nPoints += 1
|
||||||
feedback.setProgress(int(nPoints * total))
|
feedback.setProgress(int(nPoints * total))
|
||||||
nIterations += 1
|
nIterations += 1
|
||||||
|
|
||||||
if nPoints < pointCount:
|
if nPoints < pointCount:
|
||||||
QgsMessageLog.logMessage(self.tr('Can not generate requested number of random points. '
|
feedback.pushInfo(self.tr('Could not generate requested number of random points. '
|
||||||
'Maximum number of attempts exceeded.'), self.tr('Processing'), QgsMessageLog.INFO)
|
'Maximum number of attempts exceeded.'))
|
||||||
|
|
||||||
del writer
|
return {self.OUTPUT: dest_id}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user