I'm trying to devise a method for generating random 2D convex polygons. It has to have the following properties:
- coordinates should be integers;
- the polygon should lie inside a square with corners (0, 0) and (C, C), where C is given;
- the polygon should have number of vertices close to a given number N.
For example, generate random polygons that have 10 vertices and lie inside square [0..100]x[0..100].
What makes this task hard, is the fact that the coordinates should be integers.
The approach I tried was to generate random set of points in the given square and compute the convex hull of these points. But the resultant convex hull is very little vertices compared to N.
Any ideas?
Your initial approach is correct - calculating the convex hull is the only way you will satisfy randomness, convexity and integerness.
The only way I can think of optimizing your algorithm to get "more points" out is by organizing them around a circle instead of completely randomly. Your points should more likely be near the "edges" of your square than near the center. At the center, the probability should be ~0, since the polygon must be convex.
One simple option would be setting a minimum radius for your points to appear - maybe C/2 or C*0.75. Calculate the center of the C square, and if a point is too close, move it away from the center until a minimum distance is reached.
This isn't quite complete, but it may give you some ideas.
Bail out if N < 3. Generate a unit circle with N vertices, and rotate it random [0..90] degrees.
Randomly extrude each vertex outward from the origin, and use the sign of the cross product between each pair of adjacent vertices and the origin to determine convexity. This is the step where there are tradeoffs between speed and quality.
After getting your vertices set up, find the vertex with the largest magnitude from the origin. Divide every vertex by that magnitude to normalize the polygon, and then scale it back up by (C/2). Translate to (C/2, C/2) and cast back to integer.
Following @Mangara answer there is JAVA implementation, if someone is interested in Python port of it
Here is the fastest algorithm I know that generates each convex polygon with equal probability. The output has exactly N vertices, and the running time is O(N log N), so it can generate even large polygons very quickly.
X
andY
, of N random integers between 0 and C. Make sure there are no duplicates.X
andY
and store their maximum and minimum elements.X1
andX2
, andY1
andY2
.minX
at the start ofX1
andX2
,maxX
at the end, etc.).X1[i + 1] - X1[i]
), reversing the order for the second group (X2[i] - X2[i + 1]
). Store these in listsXVec
andYVec
.YVec
and treat each pairXVec[i]
andYVec[i]
as a 2D vector.An animation and Java implementation is available here: Generating Random Convex Polygons.
This algorithm is based on a paper by Pavel Valtr: “Probability that n random points are in convex position.” Discrete & Computational Geometry 13.1 (1995): 637-643.
A simple algorithm would be: