Tomé la idea de @MitchWheat y @ templatetypedef de los puntos de muestreo en un círculo y lo llevé un poco más lejos.
En mi aplicación necesito poder controlar cuán extraños son los polígonos, es decir, comenzar con polígonos regulares y, a medida que aumenta los parámetros, se vuelven cada vez más caóticos. La idea básica es la establecida por @templatetypedef; camine alrededor del círculo dando un paso angular al azar cada vez, y en cada paso ponga un punto en un radio aleatorio. En las ecuaciones que estoy generar los pasos angulares como
donde theta_i y r_i dar el ángulo y el radio de cada punto con respecto al centro, U (min, max) tira de un número al azar de una distribución uniforme, y N (mu, sigma) extrae un número aleatorio de una distribución gaussiana, y los valores de clip (x, min, max) un valor en un rango. Esto nos da dos parámetros realmente agradables para controlar qué tan salvajes son los polígonos: épsilon al que llamaré irregularidad controla si los puntos están uniformemente espaciados angularmente alrededor del círculo, y sigma que llamaré spikeyness que controla cuánto pueden variar los puntos del círculo de radio r_ave. Si configuras ambas cosas en 0, obtienes polígonos perfectamente regulares, si los levantas, los polígonos se vuelven más locos.
Azoté este rápidamente en Python y tiene cosas como esta:
Aquí está el código Python completo:
import math, random
def generatePolygon(ctrX, ctrY, aveRadius, irregularity, spikeyness, numVerts) :
'''Start with the centre of the polygon at ctrX, ctrY,
then creates the polygon by sampling points on a circle around the centre.
Randon noise is added by varying the angular spacing between sequential points,
and by varying the radial distance of each point from the centre.
Params:
ctrX, ctrY - coordinates of the "centre" of the polygon
aveRadius - in px, the average radius of this polygon, this roughly controls how large the polygon is, really only useful for order of magnitude.
irregularity - [0,1] indicating how much variance there is in the angular spacing of vertices. [0,1] will map to [0, 2pi/numberOfVerts]
spikeyness - [0,1] indicating how much variance there is in each vertex from the circle of radius aveRadius. [0,1] will map to [0, aveRadius]
numVerts - self-explanatory
Returns a list of vertices, in CCW order.
'''
irregularity = clip(irregularity, 0,1) * 2*math.pi/numVerts
spikeyness = clip(spikeyness, 0,1) * aveRadius
# generate n angle steps
angleSteps = []
lower = (2*math.pi/numVerts) - irregularity
upper = (2*math.pi/numVerts) + irregularity
sum = 0
for i in range(numVerts) :
tmp = random.uniform(lower, upper)
angleSteps.append(tmp)
sum = sum + tmp
# normalize the steps so that point 0 and point n+1 are the same
k = sum/(2*math.pi)
for i in range(numVerts) :
angleSteps[i] = angleSteps[i]/k
# now generate the points
points = []
angle = random.uniform(0, 2*math.pi)
for i in range(numVerts) :
r_i = clip(random.gauss(aveRadius, spikeyness), 0, 2*aveRadius)
x = ctrX + r_i*math.cos(angle)
y = ctrY + r_i*math.sin(angle)
points.append((int(x),int(y)))
angle = angle + angleSteps[i]
return points
def clip(x, min, max) :
if(min > max) : return x
elif(x < min) : return min
elif(x > max) : return max
else : return x
@MateuszKonieczny aquí es el código para crear una imagen de una polígono de una lista de vértices.
verts = generatePolygon(ctrX=250, ctrY=250, aveRadius=100, irregularity=0.35, spikeyness=0.2, numVerts=16)
black = (0,0,0)
white=(255,255,255)
im = Image.new('RGB', (500, 500), white)
imPxAccess = im.load()
draw = ImageDraw.Draw(im)
tupVerts = map(tuple,verts)
# either use .polygon(), if you want to fill the area with a solid colour
draw.polygon(tupVerts, outline=black,fill=white)
# or .line() if you want to control the line thickness, or use both methods together!
draw.line(tupVerts+[tupVerts[0]], width=2, fill=black)
im.show()
# now you can save the image (im), or do whatever else you want with it.
¿Qué quiere decir "al azar?" ¿Sabes algo sobre la distribución que intentas generar? – templatetypedef
@templatetypedef Aparentemente quiere un algoritmo que produzca polígonos aleatorios ** simples **, ya que en general tomar un orden arbitrario de n puntos también producirá polígonos autointersecantes. – Jorge
poner un número aleatorio de puntos en posiciones aleatorias en círculo con radio aleatorio y conectarlos consecutivamente? – dfens