Point in Disjoint Polygon - point-in-polygon

I want to check whether a given point lies inside a polygon.
I have looked into the point in polygon method using ray casting, but I'm unsure of how it will work in cases where the given polygon in disjoint. For example, if the polygon has a "hole" right in the center. How do I use this function in such cases?

I've answered a similar question here, even though it wasn't clear if I understood the OP's question too well. Well , here it is again -
Let's take a very general case .
Polygon with a hole and Intersections
The ray casting (point in polygon) algorithm shoots off a ray counting the intersections with the sides of the POLYGON (Odd intersections = inside, Even = outside).
Hence it accurately gives the correct result regardless of whether you start from inside the disjoint trapezoidal hole or the triangular hole (inner edges?) or even if a part of the polygon is completely seperated and/or self intersecting.
However, in what order do you feed the vertices of the polygon such that all the points are evaluated correctly?
Though this is code specific, if you're using an implementation that is counting every intersection with the sides of the polygon then this approach will work -
- Break the master polygon into polygonal components. eg - trapezoidal hole is a polygonal component.
- Start with (0,0) vertex (doesn't matter where (0,0) actually lies wrt your polygon) followed by the first component's vertices, repeating its first vertex after the last vertex.
- Include another (0,0) vertex.
- Include the next component , repeating its first vertex after the last vertex.
- Repeat the above two steps for each component.
- End with a final (0,0) vertex.
Example -
Let's take the picture to the right, the shell with the hole and apply the above method. The vertices of a singular continuous polygon which is mathematically equivalent to the 2 components (polygon+hole) is -
(outside)-------(inside hole)
0,1,2,3,4,5,1,0,1,2,3,4,1,0
To understand how it works, try drawing this mathematically equivalent polygon on a scratch pad.-
1. Mark all the vertices but don't join them yet.
2. Mark the repeated vertices separately also. Do this by marking them close to the original points, but not on them. (at a distance e, where e->0 (tends to/approaches) ) (to help visualize)
3. Now join all the vertices in the right order (as in the example above)
You will notice that this forms a continuous polygon and only becomes disjoint at the e=0 limit.
You can now send this mathematically equivalent polygon to your ray casting function (and maybe even winding number function?) without any issues.

Related

Oriented Bounding Box algorithm, Need some understanding/clarification of a few lines of existing (working) code

I am reviewing some MATLAB code that is publicly available at the following location:
https://github.com/mattools/matGeom/blob/master/matGeom/geom2d/orientedBox.m
This is an implementation of the rotating calipers algorithm on the convex hull of a set of points in order to compute an oriented bounding box. My review was to understand intuitively how the algorithm works however I seek clarification on certain lines within the file which I am confused on.
On line 44: hull = bsxfun(#minus, hull, center);. This appears to translate all the points within the convex hull set so the calculated centroid is at (0,0). Is there any particular reason why this is performed? My only guess would be that it allows straightforward rotational transforms later on in the code, as rotating about the real origin would cause significant problems.
On line 71 and 74: indA2 = mod(indA, nV) + 1; , indB2 = mod(indB, nV) + 1;. Is this a trick in order to prevent the access index going out of bounds? My guess is to prevent out of bounds access, it will roll the index over upon reaching the end.
On line 125: y2 = - x * sit + y * cot;. This is the correct transformation as the code behaves properly, but I am not sure why this is actually used and different from the other rotational transforms done later and also prior (with the calls to rotateVector). My best guess is that I am simply not visualizing what rotation needs to be done in my head correctly.
Side note: The external function calls vectorAngle, rotateVector, createLine, and distancePointLine can all be found under the same repository, in files named after the function name (as per MATLAB standard). They are relatively uninteresting and do what you would expect aside from the fact that there is normalization of vector angles going on.
I'm the author of the above piece of code, so I can give some explanations about it:
First of all, the algorithm is indeed a rotating caliper algorithm. In the current implementation, only the width of the algorithm is tested (I did not check the west and est vertice). Actually, it seems the two results correspond most of the time.
Line 44 -> the goal of translating to origin was to improve numerical accuracy. When a polygon is located far away from the origin, coordinates may be large, and close together. Many computation involve products of coordinates. By translating the polygon around the origin, the coordinates are smaller, and the precision of the resulting products are expected to be improved. Well, to be honest, I did not evidenced this effect directly, this is more a careful way of coding than a fix…
Line 71-74! Yes. The idea is to find the index of the next vertex along the polygon. If the current vertex is the last vertex of the polygon, then the next vertex index should be 1. The use of modulo rescale between 0 and N-1. The two lines ensure correct iteration.
Line 125: There are several transformations involved. Using the rotateVector() function, one simply computes the minimal with for a given edge. On line 125, one rotate the points (of the convex hull) to align with the “best” direction (the one that minimizes the width). The last change of coordinates (lines 132->140) is due to the fact that the center of the oriented box is different from the centroid of the polygon. Then we add a shift, which is corrected by the rotation.
I did not really look at the code, this is an explanation of how the rotating calipers work.
A fundamental property is that the tightest bounding box is such that one of its sides overlaps an edge of the hull. So what you do is essentially
try every edge in turn;
for a given edge, seen as being horizontal, south, find the farthest vertices north, west and east;
evaluate the area or the perimeter of the rectangle that they define;
remember the best area.
It is important to note that when you switch from an edge to the next, the N/W/E vertices can only move forward, and are readily found by finding the next decrease of the relevant coordinate. This is how the total processing time is linear in the number of edges (the search for the initial N/E/W vertices takes 3(N-3) comparisons, then the updates take 3(N-1)+Nn+Nw+Ne comparisons, where Nn, Nw, Ne are the number of moves from a vertex to the next; obviously Nn+Nw+Ne = 3N in total).
The modulos are there to implement the cyclic indexing of the edges and vertices.

How to check if given 3d point is outside convex hull

I'm working on a science project. I have a list of xyz-coordinates of voronoi diagram vertices, and a list of points that create my protein's convex-hull (from triangulation). Now some of the vertices lie quite far from the hull and I'd like to filter them out. How can I do it in c++ ? For now it doesn't have to be super optimised, I'm only focused on removing those points.
visualization
I was also thinking to check if a line from voronoi vertex(red crosses) to center of protein(pink sphere) is intersecting with hull face at any point, but I'm not sure how to achive that.
I've read that you can check if a point is inside a polygon by counting the times an infinite line from the point is crossing the hull, but that was for two dimensions. Can similar approach be implemented to suit my needs ?
https://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/
Let's start with the two-dimensional case. You can find the solution to that on CS.SX:
Determine whether a point lies in a convex hull of points in O(logn)
The idea is that each two consecutive points on the convex hull define a triangular slice of the plane (to some internal point of the hull); you can find the slice in which your point is located, and check whether it's closer to the internal point than the line segment bounding the slide.
For the three-dimensional case, I'm guessing you should be able to do something similar, but the search for the 3 points forming the relevant triangle might be a little tricky. In particular, it would also depend on how the convex hull is represented - as in the 2-d case the convex hull is just a sequence of consecutive points on a cycle.
I know this doesn't quite solve your problem but it's the best I've got given what you've written...

How to find closest points between two convex hull in MATLAB?

In part of an Artificial Neural Network matlab code, I want to find nearest points of two convex polygons.
I saw
dsearchn(X,T,XI)
command's description here, but that finds closest points between two sets of points, and polygons (like convexs) have infinites points.
So can you suggest any way/idea?
Notice: I'm using MATLAB 2014a. I have the coordinate of each convex's vertex point.
If you are not happy with what is provided by dsearchn, then, If I were you, I would do one of two following:
Find Nearest Neighbours on the vertices (for example which vertex of
polygon A is the NN of a given vertex of polygon B).
Pick a random point inside polygon A (you may want to compute the
convex hull of A, but you may skip that and take into account only
the vertices you know already). That random point is the query. Find
an NN of that point from the vertices of polygon B.
You may want to ask in Software recommendations for more.
Edit:
Another approach is this:
Create a representative dataset of polygon A. Set the size of the dataset yourself and fill it with samples of points that lie inside the polygon. Choose them uniformly randomly inside the polygon.
Then take a point of polygon B (either a vertex or a random point inside polygon B) and that's the query point, for which you will seek Nearest Neighbour(s) inside the representative dataset of polygon A.
Of course that's just an approximation, but I can't think of something else now.
Notice that you can of course do the same for polygon B.
With This File in File Exchange, I've find the solution.
With a little code modification, I have drawn a perpendicular bisector which I wanted. Of course, this way is time consuming.

How to find if a point is inside of a polygon using Racket

I am working an a project that, given a specific latitude and longitude coordinate, outputs the neighborhood that the point resides in. I have the latitude and longitude coordinates that make up the boundaries of several neighborhoods within a city. I have to read the neighborhood data from a file, and also read the test-points from a file. I am using the Racket programming language.
So far I have been able to read the files and create a list of points for each neighborhood, and now I am stuck. I wanted to create a polygon for each neighborhood, and then have a method that checks to see if a point lies inside that polygon. However, I cannot figure out how to do that using Racket.
Can anyone help me find out how to solve if a point is inside that polygon, or perhaps a better way to go about solving the problem?
I won't post any code for now because I don't want to solve the homework/assignment. However, I'll post some hints.
Look at the following picture:
How can we know that C is between the edges OA and OB and D is outside? It simple: we compare some angles: if the angle between OC and OA is smaller than the angle between OB and OA then C is clearly closer to OA than OB is.
Now, how do we get the angle knowing only some vectors? We can use the cosine which is monotonous: it decreases with the increasing argument. Thus, the cosine of the angle between OC and OA is greater than the cosine of the angle between OB and OA which is in turn greater that the cosine of the angle between OD and OA.
Next step is to figure out how to compute the cosine. The vector dot product helps: it's value is cosine of angle times greater than the product of operand's lengths. That is:
cos(OC; OA) = dotproduct(OC; OA) / (length(OA) * length(OC))
The dotproduct in 2D is simple:
dotproduct(OC; OA) = (C.x - O.x) * (A.x - O.x) + (C.x - O.x) * (A.x - O.x)
Combining all of the above you should have a simple test to check whether your point is in the same situation as C or as D: closer to one edge than the previous edge or not.
Now, you'll have to repeat this for every edge of the polygon and you're done. You can do this with a fold if the test is a predicate.
Note: this only works if the polygon is convex. For a concave polygon you'll need to add more tests.
Second note: In the figure, what will happen if D or C or both are below the OA line? Think about this and check if it means some more changes to the above fold method.
Last note: In a few weeks I'll post a complete code for that, assuming the assignment is over. Also, at that time I'll answer the question in the above note.
You need to start by collecting the segments of your polygon.
For the point P, you need determine if the horizontal ray starting from the point P intersects the side (segment).
If you count how many segments the point's horizontal ray intersects, then an odd number will be inside, and an even number will be outside.
(define (point-in-polygon? point polygon)
(odd?
(for/fold ([c 0]) ([seg polygon])
(+ c (if (ray-cross-seg? point seg) 1 0))))))
I have a complete solution in https://github.com/StevenACoffman/lat-long-kata-racket
An alternative Ray Casting Algorithm in Racket is https://rosettacode.org/wiki/Ray-casting_algorithm#Racket as well as in 35 other programming languages.
A more detailed walkthrough is available: https://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/

How to represent a polygon with hole(s)?

It's usually popular to work with polygons with their vertices sorted CW or CCW in vectors(2*1 or 1*2 matrices). However, how to state polygons with holes in vectors?
I'm going to apply various process on these polygons, so I want a way of representing with which I could work easily or efficiently.(i.e how to state that kind of polygons in my program in order to ease my algorithms?)
polygons are 2D and I'm programming in MATLAB.
EDIT 1 : I'm going to calculate visibility graph of these polygons(with or without holes).
As others have mentioned, a polygon with holes can be represented as an exterior boundary, plus zero or more interior boundaries, all of which are mutually nonoverlapping*. If you use nonzero winding number to determine inside/outside, be sure to specify your interior boundaries in the opposite direction as the exterior boundaries (counterclockwise for exterior and clockwise for interior, or vice-versa) so that the contour integrals are zero inside the holes.
FYI, tis kind of definition/representation has been formalized in the OpenGIS Simple Features Specification (PDF).
As far as representation:
I'd probably have a cell array of K Nx2 matrices, where the first element in the cell array is the exterior boundary, and the remaining elements (if any) in the cell array are the interior boundaries. I would use a cell array because there may not be the same number of points on each boundary.
*nonoverlapping = except at individual points, e.g. a diamond inside a square:
You can break a polygon with a hole in it into two shapes without a hole. When you're doing contour integration in a complex plane, you can create a "cut" from one edge of the polygon that brings you to the edge of the hole; integrate around one side of the hole and back; then traverse around the other side for the second polygon. You end up with two path integrals along each cut that cancel each other out.
"visibility graph" - is this for a radiation view factor calculation with shading? Or a ray-tracing graphics algorithm?
A polygon, plus a list of polygonal holes. Just be sure the various polygons don't intersect.
What do you plan to do with this thing?
It sounds like each hole is just a polygon inside the polygon itself. Perhaps you could store a vector like you describe for the outer polygon, then a vector of more polygon vectors for the holes.
Presumably you'll want to have a tree structure if you want this to be as generic as possible (i.e. polygons with polygonal holes that have polygons inside them with holes inside that, ...). Matlab isn't really great at representing tree structures efficiently, but here's one idea...
Have a struct-array of polygons.
Each polygon is a struct with two fields, 'corners', and 'children'.
The 'corners' field contains a matrix of (x,y) coordinates of the corners, accessed as "data{polyIdx}.corners(:,cornerIdx)".
The 'children' field is a struct-array of polygons.
Here's an example of some code to make a triangle with bogus children that are holes (they aren't really valid though because they will likely overlap:
polygon = struct;
npoints = 3;
polygon.corners = rand(2,npoints);
polygon.children = struct;
nchildren = 5;
for c=1:nchildren
polygon.children(c).corners = rand(2,npoints);
polygon.children(c).children = struct;
end
You could continue to recursively define children that alternate between creating holes and filling them.
What exactly do you mean under "a visibility graph" ?
Two "full" poligons, two states possible, either +1 or -1.
If you're representing a hole, you've got one with state +1 and one with state -1, which represents a hole, resulting in state 0.
If you've got overlapping polygons, you'll end up with resultant state >1. Then you can calculate the borders of a new polygon.
If you've got two polygons with holes that intersect, then first calculate the state of a new polygon which consists of outer borders of the two old ones, then deal with holes.
Anyways, ... I think you get the general principle.
Have no idea how to do it in matlab, I used it only marginally so far, and even that for very simple things.