3

I have this line vector that represents the movement trajectory of a given animal. I would like to randomly replace this vector line within a polygon, multiple times, changing its position and orientation, but without changing the trajectory itself. Is this possible? It is OK if random trajectories intersect each other, as long as they don't fall outside the polygon. Here is an example:

enter image description here

The black square is the polygon, the continuous blue line is the real trajectory, and the three dotted blue lines are examples of three random placements of the trajectory within the polygon.

How can I do this on QGIS or R?

I don't have any experience with Python.

1
  • Is this for some sort of spatial statistical analysis?
    – srha
    Commented Oct 5, 2017 at 18:13

1 Answer 1

6

Following PyQGIS code is one of possible approach:

import random

registry = QgsMapLayerRegistry.instance()

trajectory = registry.mapLayersByName('trajectory')
extent_trajectory = registry.mapLayersByName('extent_trajectory')

feat_extent_trajectory = extent_trajectory[0].getFeatures().next()

line_points = [ feat.geometry().asPolyline() for feat in trajectory[0].getFeatures() ]

feats_trajectory = [ feat for feat in trajectory[0].getFeatures() ]

convex_hull_trajectory = [ feat.geometry().convexHull() for feat in trajectory[0].getFeatures() ]

centroid_convex_hull = convex_hull_trajectory[0].centroid().asPoint()

distances = [ point.distance(centroid_convex_hull) for point in line_points[0] ]

max_distance = max(distances)

new_extent = feat_extent_trajectory.geometry().buffer(-max_distance, -1)
xmin, ymin, xmax, ymax = new_extent.boundingBox().toRectF().getCoords()

points = []
rotations = []

n = 10 #number of trajectories

for i in range(n):
    xRandom = random.uniform(xmin, xmax)
    yRandom = random.uniform(ymin, ymax)
    points.append(QgsPoint(xRandom, yRandom))
    rotation = random.uniform(0,360)
    rotations.append(rotation)

lines = []

for i in range(len(rotations)):
    feats_trajectory = [ feat for feat in trajectory[0].getFeatures() ]

    feats_trajectory[0].geometry().rotate(rotations[i], centroid_convex_hull)

    convex_hull_trajectory = [ feat.geometry().convexHull() for feat in trajectory[0].getFeatures() ]
    centroid_convex_hull = convex_hull_trajectory[0].centroid().asPoint()

    x = points[i].x() - centroid_convex_hull.x()  
    y = points[i].y() - centroid_convex_hull.y()

    feats_trajectory[0].geometry().translate(x, y)

    lines.append(feats_trajectory[0].geometry().exportToWkt())

epsg = trajectory[0].crs().postgisSrid()

uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'random_trajectories',
                           'memory')

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(len(lines)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromWkt(lines[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer) 

It produces a memory layer with all considered trajectories (in this case 10) randomly rotated and moved.

After running the code at Python Console of QGIS I got:

enter image description here

When n is changed by 1000, it was obtained result of next image . It can be observed that any trajectory intersects the outer edge.

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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