Skip to content
Permalink
Browse files
[processing] new tool: random point in given extent
Work done for Faunalia funded by Prof. António Mira (University of Évora,
Portugal, Unidade de Biologia da Conservação) and Dr. Rosana Peixoto
  • Loading branch information
alexbruy committed May 16, 2014
1 parent bae196b commit bfc33ba0ba73030ac0ed0e7bd8b07b11b52c3b99
Showing with 132 additions and 3 deletions.
  1. +5 −3 python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
  2. +127 −0 python/plugins/processing/algs/qgis/RandomPointsExtent.py
@@ -90,6 +90,7 @@
from ZonalStatistics import ZonalStatistics
from PointsFromPolygons import PointsFromPolygons
from PointsFromLines import PointsFromLines
from RandomPointsExtent import RandomPointsExtent

# from VectorLayerHistogram import VectorLayerHistogram
# from VectorLayerScatterplot import VectorLayerScatterplot
@@ -119,8 +120,9 @@ def __init__(self):
VariableDistanceBuffer(), Dissolve(), Difference(),
Intersection(), Union(), Clip(), ExtentFromLayer(),
RandomSelection(), RandomSelectionWithinSubsets(),
SelectByLocation(), RandomExtract(), RandomExtractWithinSubsets(),
ExtractByLocation(), SpatialJoin(),
SelectByLocation(), RandomExtract(),
RandomExtractWithinSubsets(), ExtractByLocation(),
SpatialJoin(),
# ------ mmqgisx ------
mmqgisx_delete_columns_algorithm(),
mmqgisx_delete_duplicate_geometries_algorithm(),
@@ -141,7 +143,7 @@ def __init__(self):
StatisticsByCategories(), ConcaveHull(), Polygonize(),
RasterLayerStatistics(), PointsDisplacement(),
ZonalStatistics(), PointsFromPolygons(),
PointsFromLines(),
PointsFromLines(), RandomPointsExtent(),
# ------ raster ------
# CreateConstantRaster(),
# ------ graphics ------
@@ -0,0 +1,127 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
RandomPointsExtent.py
---------------------
Date : April 2014
Copyright : (C) 2014 by Alexander Bruy
Email : alexander dot bruy at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""

__author__ = 'Alexander Bruy'
__date__ = 'April 2014'
__copyright__ = '(C) 2014, Alexander Bruy'

# This will get replaced with a git SHA1 when you do a git archive

__revision__ = '$Format:%H$'

import math
import random

from PyQt4.QtCore import *

from qgis.core import *

from processing import interface
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.ProcessingLog import ProcessingLog
from processing.parameters.ParameterExtent import ParameterExtent
from processing.parameters.ParameterNumber import ParameterNumber
from processing.outputs.OutputVector import OutputVector


class RandomPointsExtent(GeoAlgorithm):

EXTENT = 'EXTENT'
POINT_NUMBER = 'POINT_NUMBER'
MIN_DISTANCE = 'MIN_DISTANCE'
OUTPUT = 'OUTPUT'

def defineCharacteristics(self):
self.name = 'Random points in extent'
self.group = 'Vector creation tools'
self.addParameter(ParameterExtent(self.EXTENT, 'Input extent'))
self.addParameter(
ParameterNumber(self.POINT_NUMBER, 'Points number', 1, 9999999, 1))
self.addParameter(ParameterNumber(
self.MIN_DISTANCE, 'Minimum distance', 0.0, 9999999, 0.0))
self.addOutput(OutputVector(self.OUTPUT, 'Random points'))

def processAlgorithm(self, progress):
pointCount = int(self.getParameterValue(self.POINT_NUMBER))
minDistance = float(self.getParameterValue(self.MIN_DISTANCE))
extent = str(self.getParameterValue(self.EXTENT)).split(',')

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

fields = QgsFields()
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
mapCRS = interface.iface.mapCanvas().mapSettings().destinationCrs()
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
fields, QGis.WKBPoint, mapCRS)

nPoints = 0
nIterations = 0
maxIterations = pointCount * 200
total = 100.0 / pointCount

index = QgsSpatialIndex()
points = dict()

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

pnt = QgsPoint(rx, ry)
geom = QgsGeometry.fromPoint(pnt)
if geom.within(extent) and \
self.checkMinDistance(pnt, index, minDistance, points):
f = QgsFeature(nPoints)
f.initAttributes(1)
f.setFields(fields)
f.setAttribute('id', nPoints)
f.setGeometry(geom)
writer.addFeature(f)
index.insertFeature(f)
points[nPoints] = pnt
nPoints += 1
progress.setPercentage(int(nPoints * total))
nIterations += 1

if nPoints < pointCount:
ProcessingLog.addToLog(
ProcessingLog.LOG_INFO,
'Can not generate requested number of random points. Maximum '
'number of attempts exceeded.')

del writer

def checkMinDistance(self, point, index, distance, points):
if distance == 0:
return True

neighbors = index.nearestNeighbor(point, 1)
if len(neighbors) == 0:
return True

if neighbors[0] in points:
np = points[neighbors[0]]
if np.sqrDist(point) < (distance * distance):
return False

return True

0 comments on commit bfc33ba

Please sign in to comment.