4

I have two polygons defined as a series of 2D floating point values. They are not guaranteed to be concave or convex. They do not cross over themselves. They cannot rotate. I want to place one randomly inside the other should it be possible based on it's size. The main problem is efficiency. I have to do this about 200 or so times in a few seconds.

I've been looking into this for a couple of days now, and have made no discernible headway. Any leads would be appreciated.

ZachLHelms
  • 317
  • 1
  • 4
  • 10
  • What do you want to do with these two polygons? – Thomas Oct 16 '15 at 13:46
  • Sorry about that, specified in the title, never added it in the body. Updated now. – ZachLHelms Oct 16 '15 at 14:07
  • 1
    To propose an efficient algorithm, we may need to know more about the problem you're trying to solve and in particular, any defining characteristics of the polygons we can rely on. – Michael Petito Oct 16 '15 at 23:30
  • Not really aside from the typical traits that define a polygon. At least 3 points, doesn't cross over itself etc. Their size and shape is basically arbitrary. – ZachLHelms Oct 19 '15 at 14:29

2 Answers2

4

Disclaimer: If you are trying to pack multiple polygons inside a bigger polygon then I think, this problem is NP hard so it is unlikely that an efficient and exact algorithm can be developed to solve this problem. The polygon can continuously translate and rotate in a plane, which means the placements may be infinite and this makes the solution space of the problem also infinite. If you are just trying to find if the smaller polygon can fit inside the bigger one, I am short of an efficient answer, but as you have asked - "Any leads would be appreciated" - here is one.


Let the bigger polygon be B and smaller polygon (the one to be inserted) is S. B has a total of b points and S has a total of s points.


The image below shows a Bounding Box and a Minimum Bounding Rectangle. We use this to get the Fast Fail Filter (very simple idea... defined in next para). The box (a) shown below is faster to compute while box (b) is more accurate for filtering. Draw that box which gives better return on investment for your case. Though in the figure below they both are bounding an ellipse instead of a polygon but you get the idea.

enter image description here

(Image taken from: http://portal.ku.edu.tr/~cbasdogan/Tutorials/imageU21.JPG)

Crux: If any line of B intersects with any line of S, or if all lines of S are outside B, B cannot take S in.

Fast fail filter: Get the bounding rectangles of B and S. If you are not able to place the bounding rectangle of S inside the bounding rectangle of B, then you cannot place the polygon S inside polygon B. This way you fail faster if there is no chance of B to enclose S. Following image illustrates the three cases.

enter image description here

(Image taken from: http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/as4/figures/boundcull.gif)


Preprocessing: Determine the equation of lines that form B. Store them in a HashMap<<Point, Point>, Line> for a step that will be done later. You can uniquely define the line by slope m and intercept c and the end points of your line are going to be the key (<Point, Point>) of the HashMap.


The Algorithm:

For every S which has passed the above filter:

  1. Read the points of S and determine the lines that form S
  2. For every line of S, see if it intersects with any line of B (they are stored in the HashMap already)
  3. If there is no intersection, S is inside B and all you have to do is just draw the lines without any worry of intersection.

In the worst case, the complexity of this algorithm will be O(bs) for drawing each polygon.


This step is written brute-force to keep the algo easy to understand. Otherwise a critical optimization that will give result faster is possible here. You can filter lines of B. You need not consider a line of B for intersection with S if the endpoints of the line of B are to the left of the leftmost point of S, or to the right of the rightmost point of S or above S or below S. This can save a lot of calculations.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
displayName
  • 13,888
  • 8
  • 60
  • 75
  • 1
    I think you may have misinterpreted the question, which reads "I have **two** polygons defined as a series of 2D floating point values." You could still use your algorithm in a way (e.g. generate a bunch of randomly rotated and translated versions of polygon S, and find the first which passes the filter), but the author is probably after a more efficient algorithm. – Michael Petito Oct 16 '15 at 18:46
  • 1
    @MichaelPetito: You are correct. I am seeing if I can still edit and answer the question. If not, I will delete my answer. – displayName Oct 16 '15 at 19:03
  • 1
    I wouldn't delete your answer, since it may provide a reasonable alternative or otherwise be useful. – Michael Petito Oct 16 '15 at 19:07
  • 1
    @MichaelPetito: Have modified the text to keep its usefulness in place and added the useful disclaimer at the top. Thanks again for pointing out the mistake. – displayName Oct 16 '15 at 20:07
1

If the other answer here is useful, this is an addendum to it. It shows another approach to see if smaller polygon is inside bigger one.

To test a polygon containment, you see if all the edges of the polygon are contained. To test all the edges, you test if all the points of every edge are contained.

  1. Densify the smaller polygon by adding vertices between existing vertices. The image below shows densification of a line.enter image description here
  2. Now for the densified polygon, test if its points are all lying within the outer polygon. This test can be done by drawing lines from the point emanating to infinity on both sides and then counting how many times that line intersected with the bigger polygon.Image taken from: http://d21vdchv0ihj7g.cloudfront.net//wp-content/uploads/polygon31.png
  3. If all points are within, then the polygon is within.

First Image source.

Second Image source.

displayName
  • 13,888
  • 8
  • 60
  • 75