# Displace points by random distance and direction?

I have a shapefile of points representing households in a household survey.

In order to conceal their exact geographic location, I would like to displace these points in a random distance (uniform distribution over 0-2km) and a random direction (uniform distribution over 0-360 degrees).

How can I do this in QGIS?

Edit: Solution informed by replies:

Although displacing on the x and y axis independently creates a random direction, displacing by 2000m on the x and 2000m on the y would lead to more than a 2000m displacement in total. I thought about displacing up to 1414.2135m on both axes, but I wasn't convinced this would generate a uniform distribution over distance (I could be wrong, but I thought it would more likely create smaller distances).

The workaround I came up with was to create a random degree using the field editor rand(0,90) and a random quadrant using rand(1,4). Then I created a random distance using rand(0,2000). Let x* be the displaced x-coordinate of original point; similarly, y* is the displaced y-coordinate of the original point.

In quadrant I, x*=x+distancesin(degree) and y=y+distance*sin(90-degree)

In quadrant II, x*=x-distancesin(90-degree) and y=y+distance*sin(degree)

In quadrant III, x*=x-distancesin(degree) and y=y-distance*sin(90-degree)

In quadrant IV, x*=x+distancesin(90-degree) and y=y-distance*sin(degree)

• Another solution would be to create a 2 km buffer around the points, and use the `random points in polygon` tool to generate one random point per buffer polygon. Much simpler than calculating random angles. – csk Oct 24 '19 at 15:21

I had never done this before but I think I that you can give my solution a try. What I did was to add two new X and Y fields to my shapefile (my layer projected in UTM18N, which is meters). Then, I used the field calculator to obtain the UTM coordinates of each point but adding to it a random value between 100 and 200. I input `\$x+(rand(100,200))` and `\$y+(rand(100,200))`.

You export this layer as CSV and then reload it to QGIS as a delimited text file using these new X and Y fields. Your points will be randomly displaced. I tried it out in QGIS and it works; see the image below.

Edit: you can try some thing like `\$y+(rand(rand(-200,-100),rand(100,200)))` if you want more dispersion. I still haven't figure out how to do the 0-360 degrees part.

I hope it helps. • Thank you for your comment. Please see my edit to the original post to see if my proposed solution for degree makes sense – rachel Oct 24 '19 at 15:18
• Instead of using the field calculator to calculate new coordinates as attributes, then exporting and re-importing, try using the `geometry by expression` tool to generate new geometries in one step. Make a point out of your randomly displaced X and Y coordinates like this: `make_point(\$x+(rand(-2000,2000)), \$y+(rand(-2000,2000))`. Using -2000 and 2000 as the offset, in a CRS that uses meters, will give you a displacement of up to 2 km in any direction. – csk Oct 24 '19 at 15:18

## Use "Geometry generator"

Actually, QGIS provides a much easier way to do this: Geometry generator.

No need to create any new layer, nor any new calculated field, just add a `Geometry generator` marker in the `Symbology` pane, with soemthing similar to this content:

``````make_point(
\$x + rand(-2000,2000),
\$y + rand(-2000,2000)
)
``````

or, to get a true 2km radius:

``````with_variable('randang', rand(0,360),
with_variable('randdist', rand(0,2000),
make_point(
\$x+@randdist*cos(@randang),
\$y+@randdist*sin(@randang)
)
))
`````` • yellow dots are the original, actual points
• red dots are the randomized ones.

You can of course remove the representation of the actual points, and leave only the randomized one, which addresses your question: ## Checking the correctness

You can also check the correctness of this approach by drawing displacement lines instead of displaced points: This is accomplished selecting `LineString / MultiLineString` as `Geometry type` and with the following:

``````with_variable('randang', rand(0,360),
with_variable('randdist', rand(0,2000),
make_line(
make_point(\$x+@randdist*cos(@randang),\$y+@randdist*sin(@randang)),
make_point(\$x,\$y)
)
))
``````

Alternatively, I can suggest using a "Virtual Layer" through `Layer > Add Layer > Add/Edit Virtual Layer...`

Tested on QGIS 2.18 and QGIS 3.4

Let's assume there is a polyline layer called `"points"`. With the following Query, it is possible to achieve the result where each point will be shifted on a certain delta generated randomly.

``````SELECT points.id, points.name,
make_point(st_x(geometry)+random() % 100,st_y(geometry)+random() % 100),
random() % 100 AS delta_x, random() % 100 AS delta_y
FROM points
``````

The output Virtual Layer with its corresponding attribute table will look as following References:

The answer by @1buzz seems complete to me in terms of achieving movement in both random distance and random direction (rotation if you will). Since the x and y random displacements are independent of each other, then this accomplishes a shift in a random direction as well as a random distance from the source point, within the constraints imposed. However, you need to cater for negative displacements as well as positives, so what about \$x = `\$x+randf(-2000,2000)` and same for y, which should open up the randomized space to a square centred on the original point (as I understand it, `randf` returns a floating number rather than an integer). You might decide the integer returned by "rand" is sufficient.