Juan Bonnett
Juan Bonnett

Reputation: 1853

Python - Generate random vertices around center (x, y) position

I haven't been able to find an article or an stackoverflow question around this subject as I need it.

I'm making 2D game and I want to generate a random shaped asteroid. Every asteroid has a center, a X, Y position, I want t generate let's say 8 vertices around it (the number of vertices is variable)

enter image description here

If I can achieve this shape now I want to add a random element, let's say a variable and random distance from the center to create a random rock shape.

enter image description here

I've researched some trigonometry concept called Polar to Cartisian Coordinates but haven't been able to figure out how to apply it to this goal. Although there's tutorials for it in Javascript, it uses libraries and functions that I would have to make in python from scratch.

EDIT: So your answer is focused on explaining the formula to get the vertices around the center, these are the things that I already know how to do,

1) Draw a polygon in the graphics library I'm using 2) Get random numbers

Thank you so much in advance!

Upvotes: 4

Views: 2261

Answers (2)

Cory Kramer
Cory Kramer

Reputation: 117856

You can use the random library to randomly sample in polar coordinates. Sample an orientation, then sample a radial distance. In the following example I chose that the orientation would be uniformly distributed in [0, 2*pi] and the radius would be normally distributed with user input mean and standard deviation.

import random
import math

def generate_points(center_x, center_y, mean_radius, sigma_radius, num_points):
    points = []
    for i in range(num_points):
        theta = random.uniform(0, 2*math.pi)
        radius = random.gauss(mean_radius, sigma_radius)
        x = center_x + radius * math.cos(theta)
        y = center_y + radius * math.sin(theta)
        points.append([x,y])
    return points

As an example of how to call it

>>> generate_points(5.0, 7.0, 1.0, 0.1, 8)
[[4.4478263120757875, 6.018608023032151],
 [4.407825651072504, 6.294849028359581],
 [5.0570272843718085, 6.17834681191539],
 [5.307793789416231, 6.156715230672773],
 [4.368508167422119, 7.712616387293795],
 [5.327972045495855, 5.917733119760926],
 [5.748935178651789, 6.437863588580371],
 [3.9312163910881033, 6.388093041756519]]

If you want the points to be wound in a particular order, then I would use something like numpy.linspace to walk either clockwise or counterclockwise to sample theta. For example

import random
import math
import numpy as np

def generate_points(center_x, center_y, mean_radius, sigma_radius, num_points):
    points = []
    for theta in np.linspace(0, 2*math.pi - (2*math.pi/num_points), num_points):
        radius = random.gauss(mean_radius, sigma_radius)
        x = center_x + radius * math.cos(theta)
        y = center_y + radius * math.sin(theta)
        points.append([x,y])
    return points

If you do not want to install numpy you can write your own similar version of linspace

def linspace(start, stop, num_steps):
    values = []
    delta = (stop - start) / num_steps
    for i in range(num_steps):
        values.append(start + i * delta)
    return values

Upvotes: 6

John Zwinck
John Zwinck

Reputation: 249133

An easy way would be to choose at random one or two or three non-adjacent vertices, and simply move them a random amount which is not more than the distance to the nearest vertex.

Upvotes: 0

Related Questions