Я взял идею @MitchWheat и @ templatetypedef о точках выборки по кругу и немного потянул ее.
В моем приложении мне нужно иметь возможность контролировать, насколько странны полигоны, т. Е. Начать с правильных многоугольников, и когда я проверю параметры, они становятся все более хаотичными. Основная идея указана в @templatetypedef; ходить по кругу, принимая каждый раз случайный угловой шаг, и каждый шаг ставит точку на случайный радиус. В уравнениях я генерация угловых шагов
, где theta_i и r дают угол и радиус каждой точку относительно центра, U (мин, макс) тянет случайное число из равномерного распределения, и N (mu, sigma) выводит случайное число из гауссова распределения, а клип (x, min, max) порождает значение в диапазон. Это дает нам два действительно приятных параметра для контроля того, насколько дикими являются полигоны - epsilon, который я назову . Неправильность контролирует, равномерны ли точки равномерно по кругу, и сигма, которую я назову spikeyness, который контролирует насколько точки могут меняться от круга радиуса r_ave. Если вы установили оба из них в 0, вы получите совершенно правильные полигоны, если вы их подведете, то полигоны станут более сумасшедшими.
я взбитое это быстро в питон и получил такие вещи, как это:
Вот полный код питона:
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 здесь код, чтобы создать образ многоугольник из списка вершин.
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.
Что вы подразумеваете под «случайным»? Вы знаете что-нибудь о распределении, которое вы пытаетесь создать? – templatetypedef
@templatetypedef По-видимому, ему нужен алгоритм, который создает случайные ** простые ** многоугольники, так как в общем случае произвольный порядок n точек также будет создавать самопересекающиеся многоугольники. – Jorge
ставит случайное число точек в случайных позициях по кругу со случайным радиусом и соединяет их последовательно? – dfens