SO,
The problem
I have a question about algorithm of determining if two points are connected on 2D-plane. I have:
[x,y]
- i.e. each line looks like ['start'=>[X0, Y0], 'end'=>[X1, Y1]]
Let this lines set be named as L
. Lines can belongs one to another (i.e. one could be part of another), they can be intersected by only one point e.t.c. - i.e. there are no restrictions for them on 2D plane. But line can not be a point - i.e. start of line can not be equal to end of line.S
and E
, i.e. arrays [Xs, Ys]
and [Xe, Ye]
Now, all lines from L
are drawn on the plane. Then, S
and E
are also drawn and I need to answer the question - can E be reached from S without intersection of any lines in L? And, to be more specific - which algorithm will be optimal? By 'could be reached' I mean that there is a way on the plane from S
to E
without intersection any line from L
- and, of cause, this way could be anything, not just line.
Sample
-as you see, in sample S
and E
are not connected. Also in the sample there is a case when one line fully belongs to another (gray and purple lines) - and a case when one line has a start/end on another line (green and rose lines).
My approach
Currently, I have non-deterministic polynomial (NP) algorithm to do that. It's steps are:
so 1-st case will result in 4 new lines, 2-4 cases in 3 new lines and 5 case in 2 new lines. (lines are [A, B]
and [C, D]
)
S
subset of such polygons that contain S
. To do this, I'm using simple algorithm - counting number of intersections with polygon's edges and some line from S
to outer plane (if it's odd, then S
is inside polygon and if it's even - then outside). This is a ray-casting algorithm. Then I do that for E
S
and E
I'm simply comparing both sets. If they are equal, then E
could be reached from S
and could not be - otherwise.Why is this NP?
The answer is simple: on 3-rd step I'm performing search of all loops in 2D-graph. Since a problem of finding maximum/minimum loop length if NP, then mine is too (because I can get maximum/minimum loop length simply with sorting resulted loops set). Good information about this is located here.
The question
Since my current solution is NP, I want to know - may be my solution for the problem is an overkill? I.e. may be there are simpler solution which will result in polynomial time?
Basically the problem boils down to:
1) Determine all of the polygons enclosing some space which don't contain any other polygon. In your above example, you have 3 shapes/cycles/polygons that do not contain any others: the quadrilateral containing S, the quadrilateral containing E, and the triangle below the 2 of them.
2) Determine if S and E are on opposite inside/outside of any of these polygons.
For part 1, you have to build a graph:
Create an array of intersection points of your given line, this is N^2. Remember which 2 lines each intersection point came from. These intersection points are the vertexes of your graph.
Two vertexes are "connected" if they are from the same line and there is no other intersection point between them. Don't rely on the accuracy of floating point to determine this, obviously.
Now you wish to find the polygons in your layout. A graph may in general contain an exponential number of cycles. However, each edge may only border 2 "inner" polygons, so we are only interested in a polynomial subset of the cycles. So pick an edge, then find the next edge in the polygon, and keep repeating until you get back to where you started or determine that the first edge wasn't part of a polygon.
So suppose you are coming from edge E = (U, V), and want to find the next edge in the polygon (sharing the same vertex V).
1) Create a vector T as U - V.
2) Create the set of edges A that are adjacent to vertex V. Remove E from that set.
3) If the set is empty, then the edge isn't part of a polygon.
4) For each edge (Q, V) in A, construct a vector R as Q - V. (Remember Q and V represent points in the 2D plane).
5) Normalize R : divide it by it's length to create a vector of length 1.
6) Determine CrossProductValue(T, R).
7) The edge in A with the least CrossProductValue is the next edge in one the adjacent polygons. The edge in A with the largest CrossProductValue is the next edge in the other polygon.
CrossProductChecker(2D T, 2D R) { return (T.x*R.y - T.y*R.x); // cross product for 2 dimensions }
So use this to find your polygons. Lookup the relation between cross products and sinusoids to get an idea how this works.
============
Now that you have all of your polygons, all there is to do is check if there is one that S is inside of and E is outside of, or the other way around.
The easy way to do this is to draw a line from S to E. If it intersects any polygon (cycle from above) an even number of times, they are both inside or both outside the polygon so keep checking.
If the line intersects a cycle an odd number of times, then one is inside the polygon and one is outside, so you can say that there is no path.
You can construct a so-called "Visibility graph" that connects two obstacle vertices iif they are directly visible. Shortest path in this graph (with S and E added) will be the shortest obstacle-free path between S and E in your configuration space. Algorithms and optimisations concerning Visibility Graph are well-known and widely described.
The main difficulty you'll have is handling corner cases so you can't "leak" in some improper intersection to the other side of the segment (shared segments, endpoint as intersection, etc). Handling such corner cases is not algorithmically difficult but requires patience.
EDIT:
So let me be more formal: build a graph G(Ver, Edg)
where Ver
contains all segment's endpoints, S
and E
; and Edg
contains all pairs of vertices which are directly visible (including following the segment).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With