2
$\begingroup$

I would like to random sample points within an n-sided polygon. One idea I've thought of is to discretize the area of the n-sided polygon with triangles.

I can assign each triangle a unique number in the range $[1, M]$ where $M$ is the number of triangles. Assuming the triangle areas are equal, I can use a uniform distribution $\sim U(1, M)$ to random sample a triangle and use its centroid as the random sampled point within the polygon.

The problems with this approach are:

(1) It's a discrete approximation since I'm mapping a triangular region to a single value, i.e., the centroid. Is there a straightforward continuous approach?

(2) The assumption that the rectangles have the same area. In practice, if I have some irregular shape, I think it would be quite difficult to get all the triangle areas to be the same. Is there some sort of weighted uniform distribution you could use?

One thought that I had was to say use $\sim U(0,1)$ and for each $A_i$ (area of i-th triangle) we assign a specific range within [0, 1] where the range spans the normalized area of $A_i$. e.g., say you had 2 triangles that discretized some n-sided polygon. Say $A_1 = 50, A_2 = 100$. Then $50/(50+100) = 1/3$ and $100/(150) = 2/3$. So we could take anything within $[0, 1/3]$ and $[1/3, 1]$ from $\sim U(0,1)$ as corresponding to the first and second triangles, respectively.

What are some other approaches?

One approach that I've used with spheres is rejection sampling, but spherical surfaces are quite easily described by an equation, so rejection sampling becomes simply. For an n-sided polygon, this would seem rather difficult as there would be an equation corresponding to each side, so checking whether to accept or reject a random sample would be tedious.

$\endgroup$
5
  • $\begingroup$ @Henry n-sided. I just fixed the title. Although I'm also curious about n-dimensional polyhedron, but I'll save that for another question. $\endgroup$
    – 24n8
    Sep 21, 2020 at 19:53
  • 1
    $\begingroup$ It seems to me that the simplest thing is some kind of exclusion approach, in which you sample points uniformly from some bounding box, and then exclude anything outside the perimeter of the polygon. There are fairly straightforward algorithms for determining whether a point is inside a polygon (even a non-convex one). In two dimensions, this approach should be acceptably efficient. In high dimensions it probably won't work so well. $\endgroup$
    – Brian Tung
    Sep 21, 2020 at 19:58
  • $\begingroup$ @BrianTung Yeah, that's what I was alluding with "rejection sampling." I would enclose the polygon inside the smallest rectangle. Then you can sample x and y from a uniform distribution. But i'm not familiar with how you parameterize the bounds of a generic n-sided polygon to check if the (x,y) sampled is within polygon. $\endgroup$
    – 24n8
    Sep 21, 2020 at 20:00
  • $\begingroup$ Oops, I just now noticed you suggested this yourself. (Sorry for bad reading comprehension.) But why do you think this is tedious? Are you trying to do this by hand? There's code to do this. (ETA: Polygons are usually specified, in code, by giving an array of vertices.) $\endgroup$
    – Brian Tung
    Sep 21, 2020 at 20:01
  • $\begingroup$ @BrianTung No, I would code this, but I would want to write the code myself. Actually, now that I think about it, in code, this is probably simple. Essentially you just have $n$ constraints that describe the sides of the polygon, and when you sample (x,y) from the uniform distribution you just gotta make sure the sampled point fits the constraints right? $\endgroup$
    – 24n8
    Sep 21, 2020 at 20:03

2 Answers 2

3
$\begingroup$

The idea to triangulate is not bad. You have to choose a triangle with a probability proportional to its area. For this, form a vector with the prefix sums of the areas and draw a random number in the range $[0,\text{total area}]$. Then the interval in which the value falls tells you the triangle.

Next you need to draw a random point in the triangle, uniformly. Consider drawing two numbers in the range $[0,1]$; they define a point uniformly distributed over a unit square. Then if the point is located past the diagonal ($x+y>1$), you mirror it around the diagonal. Now you get a point uniformly distributed in a unit triangle, and finally you deform this unit triangle to the randomly chosen triangle.


Update:

A triangulation in $n$ pieces is not necessary. You can triangulate efficiently by sorting the vertices top to bottom and intersecting the polygon with horizontals by every vertex. It is a so-called sweepline process. This will partition the polygon in trapezoids, that you can further split in two triangles.

This method produces more triangles but wit a cost $O(n\log n)$, and the "penalty" of having more triangles will be very low.

enter image description here

$\endgroup$
5
  • $\begingroup$ Can you explain the idea of "deforming" the unit triangle? $\endgroup$
    – 24n8
    Sep 21, 2020 at 20:19
  • $\begingroup$ @anonuser01: unit triangle to general triangle, by an affine transformation. $\endgroup$
    – user65203
    Sep 21, 2020 at 20:26
  • $\begingroup$ This gets my vote as the best advice for software implementation (as well as being mathematically correct). $\endgroup$
    – David K
    Sep 21, 2020 at 21:42
  • $\begingroup$ The edit is an interesting idea. It's much easier for convex shapes. For non-convex shapes like the one in your example, it seems non-trivial to handle that programmatically? $\endgroup$
    – 24n8
    Sep 21, 2020 at 21:58
  • $\begingroup$ @anonuser01 I don't know what you consider to be "trivial" to program, but of all the ways I've ever tried to deal with general polygons, especially non-convex polygons, the kind of algorithm pictured at the end was by far the easiest. $\endgroup$
    – David K
    Sep 22, 2020 at 2:22
1
$\begingroup$

Your idea could work. You could decompose the polygon into triangles, a process known as polygon triangulation. Then choose a triangle randomly, but weighted by the area of the triangle. But then instead of simply choosing the centroid of that triangle, you could then choose a random point within the triangle using this approach.

If you are trying to make this as efficient as possible in a computer program, one source of inefficiency could be the polygon triangulation (although the Wikipedia page mentions the fan triangulation [given that the polygon is convex] which would be simple and efficient). It would depend on how the polygon is stored in memory.

Edit to clarify choosing the triangle randomly: Let's say the triangles are given by $T_1, T_2, ..., T_k$ and the corresponding weights are given by $A_1, A_2, ..., A_k$. Then after generating a random $x \in [0, \sum_{i=1}^k A_i)$, if $x < A_1$, the chosen triangle would be $T_1$. If $A_1 < x < A_1 + A_2$, the chosen triangle would be $T_2$. In general if $\sum_{i=1}^{m-1} A_i < x < \sum_{i=1}^{m} A_i$, the chosen triangle would be $T_m$. This is pretty much what you said, but all multiplied by the area of the polygon.

$\endgroup$
2
  • $\begingroup$ Oo yeah good point about further sampling within the triangle. Also, how do you choose a random triangle "weighted by the area of the triangle?" Is it what I mentioned in my OP about assigning range of of a uniform distribution based on the fraction the triangle takes up or is there a simpler approach? $\endgroup$
    – 24n8
    Sep 21, 2020 at 20:10
  • $\begingroup$ @anonuser01 Yes, it's pretty much what you said. I have added some more detail into my answer. $\endgroup$ Sep 21, 2020 at 20:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .