简体   繁体   中英

How can I generate a random point (x, y) 10 steps apart from y0(a, b) in xy-plane?

I have generated a random point named y0=(a,b) in xy-plane , How can I generate another random point (x,y) 10 steps apart from y0 ?

note: by 10 steps apart from the firt point I don't mean the Euclidean distance. I mean the number of steps on lattice between the two point (a,b) and (x,y) which is given by |xa|+|yb|=10

My attempt(sometimes gives wrong result).

import random
y0=(random.randint(0,50),random.randint(0,50))# here I generated the first point.
y=random.randint(0,50)

# I used the formula  |x-a|+|y-b|=10.
x=(10 -abs(y-y0[1]))+y0[0]  or x=-(10 -abs(y-y0[1]))+y0[0]

x0=(x,y)

Let's say that your new point (x, y) is on a cercle of radius 10 and center (x0, y0). The random component is the angle.

import math as m
# radius of the circle
r = 10
# create random angle and compute coordinates of the new point
theta = 2*m.pi*random.random()
x = x0 + r*m.cos(theta)
y = y0 + r*m.sin(theta)
# test if the point created is in the domain [[0,50], [0, 50]] (see comments of PM2Ring)
while not ( 0<=x<=50 and 0<=y<=50 ) :
    # update theta: add pi/2 until the new point is in the domain (see HumanCatfood's comment) 
    theta += 0.5*m.pi
    x = x0 + r*m.cos(theta)
    y = y0 + r*m.sin(theta)

Let's say you have a point (x, y)

  1. create another random point anywhere on the plane: (x1, y2) = (random(), random())

  2. take the vector from your point to the new point: (vx, vy) = (x1-x, y1-y)

  3. get the length l of the vector: l = sqrt(vx * vx + vy * vy)

  4. use l to normalise the vector (so it has a length of 1): (vx, vy) = (vx / l, vy / l)

  5. make the vector 10 steps long: (vx, vy) = (vx * 10, vy * 10)

  6. add it to your original point to get to the desired point: (x1, y2) = (x + vx, y + vy)

voilá :)

from random import random
from math import sqrt

# Deviation
dev = 50

# Required distance between points
l = 10

if __name__ == '__main__':

    # First random point
    x0, y0 = dev*random(), dev*random()

    # Second point
    x1 = dev*random()
    y1 = y0 + sqrt(l**2 - (x1 - x0)**2)

    # Output
    print "First point (%s, %s)" % (x0, y0)
    print "Second point (%s, %s)" % (x1, y1)
    print "Distance: %s" % (sqrt((x1 - x0)**2 + (y1 - y0)**2))

So, you got the formula d=d1+d2=|x-x0|+|y-y0| , for d=10 d=d1+d2=|x-x0|+|y-y0| , for d=10

Let's examine what's going on with this formula:

  • Let's say we generate a random point P at (0,0)
  • Let's say we generate y=random.randint(0,50) and let's imagine the value is 50.

What does this mean?

d1=|xp[0]|=50 and your original formula is d=d1+d2=|x-x0|+|y-y0| , so that means d2=|y-y0|=10-50 and d2=|y-y0|=-40 . Is this possible? Absolutely not! An absolute value |y-y0| will always be positive, that's why your formula won't work for certain random points, you need to make sure (d-d1)>0, otherwise your equation won't have solution.


If you wanted to consider Euclidean distance you just need to generate random points in a circle where your original point will be the center, something like this will do:

import random
import math


def random_point(p, r=10):
    theta = 2 * math.pi * random.random()
    return (p[0] + r * math.cos(theta), p[1] + r * math.sin(theta))

If you draw a few random points you'll see more and more how the circle shape is created, let's try with N=10, N=50, N=1000:

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

Now, it seems you need the generated circle to be constrained at certain area region. One possible choice (not the most optimal though) would be generating random points till they meet those constraints, something like this would do:

def random_constrained_point(p, r=10, x_limit=50, y_limit=50):
    i = 0
    MAX_ITERATIONS = 100

    while True:
        x0, y0 = random_point(p, r)

        if (0 <= x0 <= x_limit and 0 <= y0 <= y_limit):
            return (x0, y0)

        if i == MAX_ITERATIONS:
            return p

        i += 1

Once you got this, it's interesting to check what shape is created when you increase more and more the circle radius (10,20,50):

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

As you can see, your generated random constrained points will form a well_defined subarc.

this code generate a random point xy-plane named y0 then generate another point x0 10 steps apart from y0 in taxi distance .

------- begining of the code-------- import random y0=(random.randint(0,50),random.randint(0,50))

  while True:

      y=random.randint(0,50)

      x=(10 -abs(y-y0[1]))+y0[0] 
      if (abs(x-y0[0])+abs(y-y0[1]))==10:
         x0=(x,y)
         break

abs(x)+abs(y)=10 defines a square , so all you need to do is pick a random value along the perimeter of the square (40 units long), and map that random distance back to your x,y coordinate pair.

Something like (untested):

x = random.randint(-10,9)
y = 10 - abs(x)
if (random.randint(0,1) == 0):
    x = -x
    y = -y
x = x + y0[0]
y = y + y0[1]
x0=(x,y)

Clipping the x range that way ensures that all points are picked uniformly. Otherwise you can end up with (-10,0) and (10,0) having twice the chance of being picked compared to any other coordinate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM