Is Point inside a polygon? - algorithm

Given a list of points that represent the polygon in 2D, how can I determine if the point is inside the polygon.
Please note that the polygon can be either concave or convex. You can also make any assumptions about the order of the points.

The best approach to doing this is to draw a line in any direction from your point, and count the number of times that you cross the boundary of the object. If you hit the boundary an even number of times, you are outside the object, if an odd, you are inside. It is usually easiest to go along one of the axis to make this determination.
Essentially, you just have to find a way to determine if you cross a point. Use the slope of a line equation(m=(y1-y2)/(x1-x2), y=m*x(x-x1)+y1, and see if you cross within the boundaries that the point is valid. Given this equation for the line between the points, determine where your line crosses this line, and figure out if it is within the range of the line.
Incidentally, the same method works for any arbitrary dimension, just determining if you hit the face becomes more difficult.
To show a couple of examples, I've drawn a simple illustration, showing both what happens inside and outside, even with a weird shape.
Incidentally, if you hit a corner, it counts for the number of times you make a transition from inside to outside.

Select a point outside of the polygon. Draw a line between your´s and the point outside. If the line intersects the polygon an odd number of times, its inside, otherwise its outside. Zero intersections are also outside. However, this only workes for non overlapping polygons

It's a known problem with many solutions, just google it.
And read this :
http://en.wikipedia.org/wiki/Point_in_polygon

Take an arbitrary line from your point, to any point definitely outside your polygon (i.e. outside of the bounds). Check how many times that line intersects with one of the edges of your polygon. If the value is odd, the point is inside.
When checking, be careful of lines that go through a vertex, where your test may indicate two edge crossings.

Related

Determine if Line Segment Between Polygon Vertices is "Inside" Polygon

I'm trying to find an efficient algorithm that can check if a line between two vertices in a simple (edit: simple concave) polygon contains points that lie outside the domain of the polygon. The closest question I could find is this one: https://stackoverflow.com/a/36378838/12135804
But I'm not sure the answer is quite right. It might be, in which case if someone could clarify that would be great.
The basic idea is illustrated in the below picture:
Where I would like the red line to fail and the green line to succeed. I know one can't naively test the midpoint as that wont work in every case, but finding any point on the line outside the polygon's domain should disqualify it.
I appreciate any and all help!
Edit: Forgot to include cross-post link to mathematics stack exchange:
https://math.stackexchange.com/q/4040059/892519
Let's assume that the topmost point is A and the others are named B, C ... counter-clockwise, so we know what we're talking about.
If you take the red segment B-D, the one point in between is on the left. If you take the green segment D-F, the one point in between is on the right. Now, a more interesting segment would be B-E, where C is on the left while D is on the right.
In order to determine left and right, use the vector product. The length depends on the sin function, so if you get a value less than zero it's one side and more than zero is the other side.
After a lot of googling, I finally found this answer to a stackoverflow question from ~12 years ago: https://stackoverflow.com/a/693877/12135804
Assuming the edges in the polygon follow a certain order, a simple ccw test can be created using a line's starting point (p), the next ccw point in the polygon from that starting point as an inflection point (q), and the endpoint of the line (r). For the red line BD, the test would check if B,C,D is ccw (it's not). For the green line DF, test if D,E,F is ccw (it is!). This would work even if the points are non-consecutive. However, this would fail when the order of the red-green lines is reversed. For instance, if the red line became DB, the test would check D,E,B, which would pass the ccw test.
I think a more robust solution is to search for the pair of two edges in the concave polygon that share the endpoints of the line to test. For both pairs, calculate the angle between the two edges to the x-axis. Calculate the angle of the line to the x-axis as well. If the line is within the polygon, the line's angle should lie between the max and min of the polygon edges' angles for both endpoints.
Whether to test the obtuse or acute range of angles depends on some factors, I think. The red line's angle at B w.r.t. to the x axis would be in the obtuse bound between AB and BC, and the same is true at point C. Visually, it's plain to see the acute bound is what needs to be used for the max/min test at both points. If the baseline to compute the bounds from can be chosen logically, then it can be done.
Of course, this doesn't work if the line crosses outside the polygon on the way between both endpoints, but this does handle the degenerate case for a normal line-polygon intersection test. Assuming it works in every degenerate case, that is.
I won't mark this an answer because I can't prove it.
Edit: Well, I came back to thinking about this again and decided to search for questions similar to the angular bounding I posed above, and found this: https://stackoverflow.com/a/17497339/12135804
This answer satisfies not knowing the orientation of the lines! However, it assumes the minimum bound between A and B should be tested. This doesn't work for concave vertices, when AxB is < 0. In this case, a line attached to the vertex shared by lines A and B will return true if it's pointing outside the polygon, and conversely false if it's inside. I think flipping the result based on the sign of AxB should be enough to account for this, though. (a hunch that is verified in this related answer: https://stackoverflow.com/a/43384516/12135804)

How does the Even-Odd Algorithm count polygon edges?

I am wondering how the even-odd algorithm works for identifying a point in a complex polygon.
What I know right now is that it will do the horizontal search from most left to the point and count the number of edges touched.
However, what happens if the edges touched is in an intersection of 2 edges? how does it count?
Example of polygons:
The way I like to do it, which works for integer as well as floating-point coordinates, is:
for non-horizontal segments, each segment includes its bottom-most point but not its top-most point.
do not include the horizontal segments at all in the even-odd count.
This ensures that the even-odd count is correct for every point inside the polygon and every point outside, but it's not entirely consistent about points exactly on the boundary. If it matters to you, you may want to add a rule that any point that is actually on a segment is included in the polygon.
there are more ways of dealing with this problem but the safest I know of is to
Change ray direction slightly
this is numerically safe but implementation is not as easy as it sounds. Either change entire ray and compute from the start or change somewhere before the hit in question.
You need to ensure that you do not form close loops for example by zig zag pattern (so you alternate between turning CW and CCW within some cone from the original direction).
In case where ray is exactly parallel to and also touching an edge of your polygon either ignore such edge or count it twice or change the ray direction again.
Changing ray direction is always safe as it avoids singularities and numerical instabilities.
btw. This inside polygon algorithm you are using is well known by name Hit test

Algorithm for getting an area from line data (CAD fill algorithm)

I am searching for an algorithm which calculates, from a list of lines, the area a given point (P) is in. The lines are stored with x and y coordinates, the resulting area schould be stored as a polygon which may has holes in it.
Here two images to illustrate what I mean:
Many CAD applications use such algorithms to let the user hatch areas. I don't know how to call such a method so I don't really know what to search for.
Edit 1: To clearify what I'm looking for:
I don't need an algorithm to calculate the area of a polygon, I need an algorithm which returns the polygon which is formed by lines around P. If P is outside any possible polygon, the algorithm fails.
(I also edited the images)
Edit 2: I read the accepted answer of this possible duplicate and it seams I'm looking for a point location algorithm.
I also stumpled across this site which does exactly explains what I'm looking for and more important it led me to the open-source CGAL library which provides the functionality to do such things. Point 4.6 of the CGAL manual gives an example how to use this library to form a region from a bunch of line segments.
One way to do it is to imagine a line from P to infinity. For each polygon test each edge to see if it crosses the line. Count up how many lines cross. If its even then the point is outside the polygon, if its odd then the point is inside the polygon.
This is a fairly standard mathematical result. If you want to get a little deeper into the subject have a look at https://en.wikipedia.org/wiki/Winding_number.
I did a fairly similar things earlier this week Detecting Regions Described by Lines on HTML5 Canvas
this calculates a the polygon around a point given a set of lines. You can see a working example at the jsfiddle mentioned in the answer
the difference is that it uses infinite mathematical lines rather than line segments, but it could easily be modified for this example.
An outline algorithm
First construct two data-structures one of line-segments one of intersection-points of line-segments. In each record which two lines give each intersection, so you can flip from
one to the other. You can get this by pair-wise intersection of line-segments.
It might be easiest to cut the segments at the intersection points so each segment only have two solutions on it, one at each end. We assume we have done this.
Prune the data-structures, remove all line-segments with no intersections and only one segment - these cannot contribute.
Find possible starting lines. You could calculate the distance from each line to the point and take the smallest. You could check for intersections with a line from the point to infinity.
Walk around the polygon anti-clockwise. With you starting line find the most anti-clockwise end. At that point find the most anti-clockwise segment. Follow that and repeat. It may happen that closed loop is formed, in which case discard all the segments in the loop. Continue until you get back to the starting point.
Check if the polygon actually encloses the point. If so we are done. If not discard segments in the polygon and start again.

Please help me with a trigonometric algorithm

Here is a graphic representation of the problem:
http://i.imgur.com/aBG3p.jpg
Given a starting point (x1,y1) and a destination point (x2,y2), I must determine if the path between the two points is open or, if it is not open, which coordinate the collision happens on.
It would be a trivial problem except for the special rules involved:
The line can intercept a point, call it (i,j) to a small and varying degree without causing a collision. If (i,j) is directly adjacent to (x1,y1), we can safely cut about 0.4 over its corners without triggering a collision. However we cannot cut 0.4 over if going directly through it, only over the corners. This number tapers off to about 0.2 as we get further away from (x,y). Unfortunately I'm just trying to reconstruct something I saw once, so I don't know the exact values, I'm just approximating them.
The caveat to 1: If the space directly beside (i,j), in the plane that we are intersecting, on the side that we are intersecting, is also occupied, there will be a collision no matter what. The collision will happen (i,j) if we intercept it by too much, otherwise in the relevant adjacent tile.
I've made several tries to crack this problem, always ending up with false negatives and/or the collision resulting on the wrong tile. I tried to do it without considering the angle, just by looking at the decimal points of x and y as we travel down the line. I'm not sure if it is possible to do this, or if I must use the angle in some way, or if using the angle in some way could make my life easier.
Please help if you can!
It seems like you could get results similar to what you describe by treating the occupied grids as containing unit circles. That would let you pass corners, but block on any 2 adjacent ones, since they contact.
So I'd try using your current collision method to check rectangles quickly, then refining it once you found a collision, by testing the line entering the box against a circle centered in it.

Algorithm for finding empty areas

does anybody know of a good algorithm for this task:
a multi polygon contains the reserved areas
find an empty position for the given polygon which is closest to its original position but does not intersect the reserved areas
I have implemented some very basic algorithm which does the job but far from optimally.
Thank You!
Edit:
my solution basically does the following:
move given polygon in all possible directions dx and dy
check wether the new intersection is less than the previous intersection
if so, use new position and make sure that you don't move your polygon back and forth at the same position
repeat these steps a maximum of N times
Example: it is intended for placing text which should not overlap with each other.
One method that immediately pops into my mind is to shoot a ray (i.e. measure a line segment) from the original position to every vertex of the polygon. Do a comparison on those distances, and then based on those comparisons, narrow it down to the minimally far away line segment of the polygon. Compute the perpendicular intersection of that line with the origin, and you'll get the minimally far away point. If the vertex comparisons don't lead you down the right path, just shoot off lines in random directions, and just stop when you're happy with the result. It doesn't sound like you require optimality.
Let's look at the original problem: making sure that one piece of text doesn't overlap another. Presumably this is for labelling a map. The way I do it is this: draw the text invisibly, checking for overlap (by using a specialised graphics context that instead of drawing a pixel, checks whether a pixel is already there) then try another position along the line on which the text is to be placed - usually a street. I try the middle of the line first, then successive positions further and further left and right of the middle. If that fails I try again with a condensed (narrower) font.

Resources