Suppose there is a polygon with no holes and self-intersections (i.e. a simple polygon) defined by n
vertices. Choose a reflex vertex v
of this polygon.
I'd like to find any other vertex u
of the same polygon which is "visible" from the vertex v
. By visible I mean, that a line segment between v
and u
lies completely inside the polygon.
Is there an algorithm to do that in O(N)
time or better? Is there an algorithm that can find all visible vertices in O(N)
time?
A quick research suggests that for a given polygon and any point inside this polygon a visibility polygon can be constructed in O(N)
. I assume that finding a single visible vertex should be even easier.
I've modified the algorithm as it was incorrect. I hope this time it covers all cases!.
Start from a reflex a, let a' the next vertex and follow the polygon until you find an edge that crosses a--a' in the side a', let b the point of intersection of this edge with the line a--a' and c the end point of the edge (the one to the right of a--c).
Now continue going through the edges of the polygon, and if an edge crosses the segment a--b from left to right then set b to the new point of intersection and c to the end vertex. When you finish we have a triangle a--b--c. Now starting again from c look every vertex to see if it is inside the triangle a--b--c and in that case set c to the new vertex. At the end a--c is a diagonal of the polygon.
Here is an implementation in C that assumes that the reflex point a is in
P[0]
:Just keep going in some direction through vertices starting with V and update list of visible vertices. If I didn't miss anything, that will be O(n).
For simplicity let's call V visible.
I've tried for a day to put it in words, failed and used pseudo-code :)
You could use a triangulation of the polygon.
Assuming you have a triangulation
T
, a set of visible verticesU
for a vertexV
could be found by examining associated internal edges in the triangulation. Specifically, if the set of triangles attached toV
are traversed and the internal edges identified (those that appear twice!), the setU
is all edge vertices exceptV
.Note that this is not necessarily all visible vertices from
V
, just a set with|U| >= 0
(must be at least one internal edge from V). It is efficient though - onlyO(m)
wherem
is the number of triangles/edges visited, which is essentiallyO(1)
for reasonable inputs.Of course, you would need to build a triangulation first. There are efficient algorithms that allow a constrained Delaunay triangulation to be built in
O(n*log(n))
, but that's not quiteO(n)
. Good constrained Delaunay implementations can be found in Triangle and CGAL.This problem was solved 30 years ago:
There is a very nice paper by Joe & Simpson, 1985, "Visibility of a simple polygon from a point," that offers carefully verified pseudocode: (PDF download link). This surely has been implemented many times since, in many languages. For example, there is a link at the Wikipedia article on the topic.
You can test any individual vertex in O(n) time, and hence test all vertices in O(n^2). To test any if any individual vertex U is visible from V, construct the line between V and U. Let us call this line L. Now, test L to see if it intersects any of the polygon edges. If it does not, U is not obscured from V. If it does, U is obscured.
Further, you can test if L lies within the polygon like so: Assume the incident edges on V are E1 and E2. Calculate the signed angles between E1 and E2 (call this a1) and between E1 and L (call this a2). The sign of a2 should be the same as a1 (i.e., L is on the 'same' side of E1 as E2 is), and a2 should be smaller than a1 (i.e., L 'comes before' E2).
Be careful with your intersection tests, as L will trivially intersect the polygon edges incident to V. You can ignore these intersections.
Also, if U shares any of the edges incident to V, U is trivially visible from V.