0

Let's say my window's dimensions are 400 width by 600 height.

It's relatively easy to generate a random point on a single side, let's say the top of it:

random.randint(0, width) 

But what would be the smartest way to get this to work for all 4 sides so that a random point is generated outside a rectangle?

If I do

pos_x = [random.randint(0, width)] pos_y = [random.randint(0, height)] 

They will only show up on the corners, which makes sense. The only way I can think of is to randomly create a point inside the rectangle, compare what axis is closest to a border, then clamp it. Thing is I don't know how to do this elegantly without doing 4 checks for each side (which feels redundant). I feel like there is an easier solution for this?

Here's a solution that almost works but it's so long winded. Just realized that this gets less points in the corners.

# Create a random point inside the rectangle pos_x = random.randint(0, width) pos_y = random.randint(0, height) # Get a distance for each side left_border = pos_x right_border = width-pos_x top_border = pos_y bottom_border = height-pos_y borders = [left_border, right_border, top_border, bottom_border] index_1 = 0 index_2 = 2 closest_side = 0 # Get closest from left/right borders if right_border < left_border: index_1 = 1 # Get closest from top/bottom borders if bottom_border < top_border: index_2 = 3 # Get closest border if borders[index_1] < borders[index_2]: closest_side = index_1 else: closest_side = index_2 if closest_side == 0: obj.pos.x = 0 # Clamp to left wall elif closest_side == 1: obj.pos.x = width # Clamp to right wall elif closest_side == 2: obj.pos.y = 0 # Clamp to top wall else: obj.pos.y = height # Clamp to bottom wall 
5
  • Where is (0, 0), the upper left corner of the recrangle? Commented Jul 2, 2016 at 15:40
  • @ayhan Yes that is correct. Commented Jul 2, 2016 at 15:41
  • 1
    Possibly related: Pythonic way to generate random uniformly distributed points within hollow square lamina Commented Jul 2, 2016 at 15:45
  • Thanks for the link though the solution seems convoluted! I found a solution and will update my post with it. Maybe someone can see if it can be more elegantly done. Commented Jul 2, 2016 at 16:02
  • Original post updated! Commented Jul 2, 2016 at 16:12

1 Answer 1

2

Sorry; completely misinterpreted the question the first time.

If you just want to pick a point randomly on the edge of a rectangle, try something like this:

p = random.randint(0, width + width + height + height) if p < (width + height): if p < width: obj.pos.x = p obj.pos.y = 0 else: obj.pos.x = width obj.pos.y = p - width else: p = p - (width + height) if p < width: obj.pos.x = width - p obj.pos.y = height else: obj.pos.x = 0 obj.pos.y = height - (p - width) 

Simply, it picks a random point on a line the same length as the perimeter of the rectangle, then piecewise wraps that line around the rectangle to give x and y coordinates.

To ensure that the distribution stays uniform at the corners, each of the four segments are taken as inclusive-exclusive intervals (can be 0, cannot be width or height) and they're placed such that each one of them starts in a different corner.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for coming back, I'll check this out soon.
Just tested out in Java. It's a smart idea to "unwrap" it like that as a single line. Thanks for the help!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.