5

I am trying to create random points along a line, however I only want to do it in the selected area. Is there a way to do this?

2
  • 1
    Could you expand on your question a little bit? Maybe some screenshots? It's hard to understand exactly what you are asking or what you have tried.
    – MaryBeth
    Apr 4, 2017 at 18:21
  • 1
    There's no way to directly do this, you'll have to make a new layer with only the segments of the line you want points along, and then generate points along that line.
    – coneypylon
    Apr 4, 2017 at 21:13

1 Answer 1

4

At the moment, the Random points along line tool creates random points on all lines in your layer regardless if the Use only selected features option is enabled in Processing > Options > General.

However, you could use the following script which is heavily based on the source code for the tool. The script allows you to:

  • Create random points for each selected line.
  • If no lines are selected, create random points shared between all lines (which is what the original tool does).
  • (Optional) Treat all selected lines as a single feature.

To run it, go to:

Processing Toolbox > Scripts > Create new script

Then copy/paste the code below. Make sure to save the script in your /.qgis2/processing/scripts directory.

##Random points along line(s)=name
##Input_layer=vector line
##Group_selected_features=boolean False
##Number_of_points=number 1
##Minimum_distance=number 0.00
##Output=output vector

from qgis.core import QgsField, QgsFields, QGis, QgsSpatialIndex, QgsDistanceArea, \
QgsFeatureRequest, QgsGeometry, QgsPoint, QgsFeature
from PyQt4.QtCore import QVariant
import random

def checkMinDistance(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

layer = processing.getObject(Input_layer)

fields = QgsFields()
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
writer = processing.VectorWriter(Output, None,
    fields, QGis.WKBPoint, layer.crs())

nPoints = 0
nIterations = 0
maxIterations = Number_of_points * 200
featureCount = layer.featureCount()
total = 100.0 / Number_of_points
index = QgsSpatialIndex()
points = dict()
da = QgsDistanceArea()
request = QgsFeatureRequest()
random.seed()

while nIterations < maxIterations and nPoints < Number_of_points:
    features = layer.selectedFeatures()
    if features:
        if Group_selected_features:
            feat = []
            feat.append(random.choice(features))
        else:
            feat = layer.selectedFeatures()
    else:
        feat = layer.getFeatures()

    for f in feat:            
        fGeom = QgsGeometry(f.geometry())

        if fGeom.isMultipart():
            lines = fGeom.asMultiPolyline()
            lineId = random.randint(0, len(lines) - 1)
            vertices = lines[lineId]
        else:
            vertices = fGeom.asPolyline()

        if len(vertices) == 2:
            vid = 0
        else:
            vid = random.randint(0, len(vertices) - 2)
        startPoint = vertices[vid]
        endPoint = vertices[vid + 1]
        length = da.measureLine(startPoint, endPoint)
        dist = length * random.random()

        if dist > Minimum_distance:
            d = dist / (length - dist)
            rx = (startPoint.x() + d * endPoint.x()) / (1 + d)
            ry = (startPoint.y() + d * endPoint.y()) / (1 + d)

            # generate random point
            pnt = QgsPoint(rx, ry)
            geom = QgsGeometry.fromPoint(pnt)
            if checkMinDistance(pnt, index, Minimum_distance, 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
        nIterations += 1

del writer


Example:

  1. Here is the interface when you run the script:

    Script interface


  1. Running the script on one selected line:

    One selected line


  1. Running the script on two selected lines with the Group selected features option checked:

    Two selected lines

6
  • I can't seem to control the number of points it places. I input 1 but it generated 385. help
    – pbice
    Apr 5, 2017 at 19:02
  • @pbice - Could you share your line shapefile? I tested this on straight, curved and multi lines and it seems to work fine.
    – Joseph
    Apr 6, 2017 at 9:46
  • I figured out what is wrong. Is there a way to have it treat all selected features as one feature and only generate one random point somewhere on group of selected features?
    – pbice
    Apr 6, 2017 at 16:29
  • @pbice - Edited post, the script now includes an additional option to allow you to treat selected features as one. Hope this helps :)
    – Joseph
    Apr 7, 2017 at 13:42
  • 1
    The Random points along line algorithm supports selections (QGIS 3.10.2 - I have not tested with earlier versions). Feb 25, 2020 at 2:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.