8

My question is very similar to Plow's Question; but with this difference:

How can I find the maximum convex area that can fit inside a non-convex region?

For an example, consider this non-convex region:

Image

Any ideas or solution would be appreciated, thanks.

Community
  • 1
  • 1
Zakhar
  • 313
  • 1
  • 4
  • 12

1 Answers1

9

I wrote an answer to this question on the Mathematics Stack Exchange, and included an image which I created using a proof-of-concept implementation. The approach used for this might work for many practical applications, so I'll describe it here in a bit more detail.

Take your shape, and approximate it using a polygon. Identify runs of consecutive vertices which have interior angle > 180°. For each such run, iterate over all possible tangent lines. A tangent line to a run is a line connecting two consecutive vertices, at least one of which lies within the run. This means that the first line is defined by the last vertex before the run and the first vertex of the run. Take the inward-pointing half plane defined by this line, and intersect it with your shape, then compute the area and compare it against the best solution found so far.

In a simplistic approach, you'd simply set up a recursive scheme to try out all possible line combinations. this means a time complexity of O(nm), where n is the number of vertices and m is the number of runs. In a more elaborate approach, you might leverage the fact that a line which does not intersect any other line inside the shape can be chosen independently from these others. The same holds for groups of lines which don't intersect one another inside the shape. Some choices of lines will cut away a different run altogether, such that the choice made for that run becomes irrelevant. So there is a lot of potential for clever algorithms here, depending on how much effort you can invest and what performance you require.

If your input is a polygon, then a line touching a non-convex vertex need not neccessarily coincide with either the incoming or the outgoing edge of the polygon, but might be rotated arbitrarily between these two limits. For this case, the above approach might yield a non-optimal solution. But since you stated in a comment that we may assume “non-polygonal” shapes, which I take to mean “smooth”. In this case, you have a well-defined tangent at every point, and every tangent will be reasonably close to an edge of the polygonal approximation.

Contrary to what I believed initially, the above should work for shapes with holes as well, since the boundary of a convex hole would result in a non-convex run of the shape itself. So that run will ensure that you investigate all possible ways to cut away the hole. SImilar for non-convex holes: the relevant runs will ensure you cut them out as well, without loosing any convex solutions.

Applied to your example image, the algorithm yields the following result:

Algorithm applied to example shape

The non-convex runs of vertices are colored red, the best set of lines in blue and the resulting area in green. The polygon behind this has 269 vertices. The implementation was done in Java, with little regard for performance, a brute-force recursive search of all possible combinations, and some assumptions which work for this input data but may fail in general.

Community
  • 1
  • 1
MvG
  • 57,380
  • 22
  • 148
  • 276
  • How can i extend procedure to general case? (if i change code to work for other regions; which parts should be changed? - I'm very new to java programming! from this I wrote a letter and sent to you) – Zakhar Jul 31 '13 at 21:20
  • 1
    @ZiaPandorra: Java was my choice since it does area intersections out of the box. I'll list some implicit assumptions that I know of. The starting point of the polygon will be well within a convex area, which is assumed in several places related to `inflectionPoints`. The cyclic interpretation of `pts` assumes no holes. The arbitrary length of 1200 used to approximate the half plane using a square might need adjusting. `findInflections` would need some sign changes if the overall orientation were reversed. This list might be incomplete. For performance, scrap the Java and restart in C++. – MvG Jul 31 '13 at 21:43
  • Oh! Scrapping the java code is very easy for you, but not for me! And how about coordinates? Did you insert them one by one?! – Zakhar Jul 31 '13 at 22:49
  • 1
    @Zia: The code is too ugly to copy and use. Treat it as a means of explaining what to do, try to understand that explanation and follow it in a language where you feel at home. For the coordinates: I took your image, imported it into inkscape, traced it to a filled area representing the black outline, took the inner boundary of that, grabbed its SVG description, transformed that using an Emacs macro, and finally tweaked some minor parts manually, e.g. applying the global y offset from the layer. If you know SVG, you may recognize the distinction between `c` and `C` in the path data. – MvG Jul 31 '13 at 23:09