0

Given a polygon that may be concave and may have holes, how can I get the largest simple convex polygon composed of a subset of its vertices?

ie, given the simple concave polygon:

simple concave polygon

p = Polygon([(30, 2.01), (31.91, 0.62), (31.18, -1.63), (28.82, -1.63), (28.09, 0.62),  (30, -0.001970703138552843)])

I want the largest simple convex polygon (perhaps the same but without the leftmost point (28.09, 0.62) and replace (28.82, -1.63) with (30, -1.63)). Like this:

simple convex polygon

This is just an unmeasured example. It may be that in fact both (28.09, 0.62) and (30, 2.01) must be removed, if this produces a larger area, such as might result from the cut indicated by the green line here:

alternate means of cutting the polygon

But, assuming the first cut was correct, If we added a hole to the "other side":

complex polygon

p = Polygon([(30, 2.01), (31.91, 0.62), (31.18, -1.63), (28.82, -1.63), (28.09, 0.62),  (30, -0.001970703138552843)], 
[[(30.1,0.62), (30.1,1.25), (31, 1.25), (31,0.62)]])

the largest simple convex polygon might in such cases rotate to the other half of the polygon, so instead of dropping the previous point, it would drop (30, 2.01) and replace (31.91, 0.62) with a point between that and (31, -1.63). Obviously, in this case it would throw out all of the vertices of the hole.

commentary

Any hole that would be left intact inside the polygon would introduce a concave angle to the polygon by definition. in the case that there is a hole in the input polygon, at most one edge from it can remain in the output polygon (and, by definition of "simple polygon", that edge would be a member of the exterior coordinates).

There's a little bit of sloppiness in this definition so I should try to be more clear. All interior and exterior vertices are members of the set of possible points in the output simple polygon. So are all points that intersect the interior and exterior bounds (so the line segments between them). The selection of points should result in a simple, convex polygon that is inscribed in the source polygon. In the case that the source polygon is a simple, convex polygon, it should return the same polygon as output. It is quite possible to have whole families of candidate solutions with equal area. If they are maximal, any one of them will do.

Sketch approach: if you throw out cuts like in the sample with the green line, then all that remains are removal of points with projections from segments. So you could count all interior and exterior points as a set, and exclude subsets of 0 or more of them, then find the largest convex polygon. So, either just exclude the point or when excluding a point produces a new concave angle, project from the line segment on that side of the angle to the line segment on the other side of the polygon (this is the approach used to produce the first sample solution image). Revisiting the green line cuts, these are lines that bisect the polygon and tangent the center point of the concave angle. If this bisection must run perpendicular to the line from the center point to the centroid of the remaining polygon, then this is not much more complex. But I'm not sure that that is true. And in any case, that is a lot of polygons to consider.

note: at first I marked a duplicate, thinking this is essentially a more complicated version of another question (Finding largest subset of points forming a convex polygon but with holes). However, this approach does not allow for addition of new vertices in the solution. For example, Delaunay triangulation of the first shape in this article produces no new points:

[ 'POLYGON ((28.09 0.62, 28.82 -1.63, 30 -0.001970703138552843, 28.09 0.62))', 
  'POLYGON ((28.09 0.62, 30 -0.001970703138552843, 30 2.01, 28.09 0.62))', 
  'POLYGON ((30 2.01, 30 -0.001970703138552843, 31.91 0.62, 30 2.01))', 
  'POLYGON ((31.91 0.62, 30 -0.001970703138552843, 31.18 -1.63, 31.91 0.62))', 
  'POLYGON ((28.82 -1.63, 31.18 -1.63, 30 -0.001970703138552843, 28.82 -1.63))']

The article provided as possible duplicate only counts subsets of the points to find the maximal convex hull -- ie, it does not introduce points on the line.

roberto tomás
  • 4,435
  • 5
  • 42
  • 71
  • 1
    Can you show an example illustrating what you'd want the resulting shape to look like? A simple convex polygon that contains a subset of the original vertices sounds a lot like the ["convex hull"](https://shapely.readthedocs.io/en/stable/manual.html#object.convex_hull) to me – Cory Kramer Dec 28 '21 at 19:48
  • Hey Cory, I added it to the first sample.. the thing is, Im not certain that this result is the _largest_.. but it likely is. – roberto tomás Dec 28 '21 at 19:56

1 Answers1

1

I am not really sure your problem is well specified (or rather, they way you describe it it is reduced to a well-known, simpler problem).

First, let me introduce you the idea of the Convex Hull:

Given a list of points, the convex hull is the smallest convex (simple) polygon that contains all points.

The shape of the CH is essentially what you would get if you were to "place a rubber band" around the points so that it touches the outer ones.

Now, there is a straightforward property of the CH:

Given a set of points, the are of their CH is larger (or equal) than the area of any other (simple) polygon those may form.

This is true because i) If they form a convex polygon, then they form the CH by definition. ii) otherwise, they form some non convex shape. Visually, you can get from the CH to that non convex shape by "removing triangles" comprised of 2 points on the CH and one inner point. So you are removing area, so the CH has the largest area.

So, the largest convex polygon comprise of all the vertices is the CH.

Now, about selecting a subset of the original vertices: This will obviously give you a smaller (or equal) -sized shape. So there is no point in selecting any subset, really.

Also, holes don't really impact this argument. Keeping the whole is obviously to your benefit, since you can add the area around the hole.

So, the final answer (unless I missed something), is that all you need is the Convex Hull.

Fortunately, there are some good python libraries for computing, plotting and messing around with convex hulls.

kyriakosSt
  • 1,754
  • 2
  • 15
  • 33
  • yes I started with a convex hull actually. The problem with this is that it does not exclude holes or surfaces external to the polygon described by the set of its points. I am not looking for the convex external wrapper of a set of points, Im looking for the largest convex polygon inscribed in my polygon (which might in fact be all of it, if it was a convex polygon wihtout holes to begin with.) – roberto tomás Dec 28 '21 at 20:52
  • specifically, imagine a shape like the letter H, where each part of the "H" has a thickness. the convex hull of that is a rectangle, like ⬛ . But this contains points not in "H", which is an issue for me. – roberto tomás Dec 28 '21 at 20:55
  • I voted you up because this was such a lovely and thoughtful answer :) – roberto tomás Dec 28 '21 at 21:03
  • Oh, I see now what you meant. Let me try and see if I can come up with something – kyriakosSt Dec 28 '21 at 21:35
  • Well, now I think you problem has two distinct parts: 1) Remove the "hole-part", 2) Find the maximum convex subset of the remaining shape. Assuming this is what you want, I am providing a small algorithm in my next comment – kyriakosSt Dec 28 '21 at 21:43
  • 1
    1. First do a Delaunay triangulation of your shape, ignoring the hole. Now, consider the hole as a separate shape. 2. Find all triangles that intersect with the hole (a decent library should be able to do that). 3. Throw those triangles away, and construct a new "subset" polygon without them. 4. Compute the "largest convex sub-polygon" of the new shape. This is your answer. To perform 4., take a look at [this question](https://stackoverflow.com/questions/21778506/finding-largest-subset-of-points-forming-a-convex-polygon) – kyriakosSt Dec 28 '21 at 21:48
  • that is excellent! the answer even starts with gloss about an approach with runtime similar to my naive approach, so I'm super happy for an improvement. thank you – roberto tomás Dec 29 '21 at 13:55
  • one thing about that approach though, a hole doesn't _necessarily_ invalidate a segment of the shape. but, I can think through how to process holes. great suggestion – roberto tomás Dec 29 '21 at 14:12
  • actually there is a separate issue which I described in the op which makes this approach untenable. – roberto tomás Dec 29 '21 at 14:33
  • I see what you mean. Unfortunately, I think it requires some effort thinking about it, so I am not sure it is suitable for a SO question/comments discussion. – kyriakosSt Dec 30 '21 at 20:02