Visibility graphs have many applications, including ﬁnding the shortest path, robotic motion planning and the art-gallery problem. The ﬁrst non-trivial algorithm developed for ﬁnding the visibility graph runs in O(n2 log n) and is presented in this paper. Its correctness, space, and time usage are mathematically analyzed. Because faster algorithms to solve this problem have been discovered, this paper is somewhat original in its analysis and implementation details of an otherwise forgotten algorithm.

II. A.

INTRODUCTION Visibility Graph

Visibility is an important property in computational geometry and is used in many diﬀerent types of problems, structures and algorithms [8]. One of the most basic structures is the visibility graph, where an input graph G describes a set of geometric primitives in an d-dimensional space, and the output visibility graph Gv describes the visibility between every vertex and every other vertex in G. Here, we deﬁne visibility as the ability to run a straight line between two vertices without crossing any other edge in the input graph G. In this way, two visible vertexes are said to be unobstructed by any obstacle, and a line is drawn between them in the output Gv . An example visibility graph in d = 2 dimensions Euclidean space is shown in Figure 1. The set of geometric primitives inG can consist of a variety of diﬀerent types of shapes: rectilinear, circular, line segments, convex polygons or, most generally, simple polygons. Many diﬀerent algorithms have been developed based on the assumption of which types of geometric primitives are allowable. In this paper we will focus on simple non-intersecting line-segments, so as to simplify our proofs and analysis. Very little modiﬁcation would be required to expand the problem space to general polygons. The layout of the geometric primitives is another variFIG. 1: Top: An input graph G consisting of a set of simple line segments. Bottom: a generated visibility graph Gv describing all possible non-obstructed connections between each vertex.

∗ david.t.coleman@colorado.edu;

www.davetcoleman.com

ation between computational geometry papers. In some, visibility within a simple polygon is the only problem space, but more often there exists obstacles within the space, also referred to as holes or islands. Another variation of the visibility graph for all points is ﬁnding the visibility tree for just one point, which is simply a subproblem of the visibility graph for all points.

2
B. Applications

Visibility graphs are most often thought of for use in Euclidean shortest-path problems, were a start point s and end point t are given and the task is to ﬁnd the optimal continuous path through the obstacle space without violating physical constraints. This application exploits the fact that the shortest paths are found on the arcs of the visibility graph. Once the visibility graph has been constructed, the shortest path problem can be trivially solved using well known algorithms such as Dijkstra’s [6], A* search[5], or Floyd-Warshall [3] algorithms. Robotic motion planning is a common sub problem of the shortest path problem, as demonstrated in Lozano-Perez and Wesley’s 1979 collision-free paths algorithm [11]. One of the most famous examples of visibility graphs used in robotic motion planning is Shakey the Robot [11]. However, the application of visibility graphs realistically limits the workspace to two dimensions and is generally computationally intractable for modern real-world robotics problems. Sampling-based approaches are considered the current state of the art and, although unable to determine that no path exists, have a probability of failure that decreases to zero as more computational time is spent [7]. Additional applications of visibility graphs include ﬁnding the minimum dominating set to help solve the art gallery problem and in solving pursuer-evader problems [10]. Finally, visibility graphs can be used to optimize radio antenna placement, urban planning and architectural design [1].

average, or handle sparse graphs more eﬃciently. One of the last papers published on visibility graphs during this time period achieved O(|e| + n log n) time bounds, which are output-sensitive algorithms optimal for graphs of a certain minimum density threshold [4].

III. A.

METHODS

Description of the Algorithm

Lee’s O(n2 log n) algorithm computes the visibility graph Gv from G(V, E ) by computing the visibility graph of a single vertex n times. For each vertex vi ∈ V , the visibility of all other vertices is calculated by 1) sorting all surrounding vertices in angular order from some starting scan line, 2) using a rotating plane sweep technique to visit each vertex in angular order and 3) keeping track of the distance of each surrounding line segment on the scan line in a sorted data structure. The following details these 3 procedures: For each vi ∈ V a visibility tree is generated describing the visibility of all other points vj ∈ V − vi with respect to vi . Each visibility tree is created by setting vi to be the center vertex c. A starting scan line vector s is initialized for each c, with the origin of the vector at c. Its direction is irrelevant for the algorithm but in this paper and implementation s will be assumed to be the horizontal unit vector ˆ i pointing straight and to the right from c, i.e. s = ˆ i = [1, 0]. From scan line s = ˆ i we calculate the counter clockwise angle θi = angle(sc→vi , ˆ i) for every vertex vi ∈ V − c. The angles are inserted to an optimally sorted data structure A from smallest to largest.

C.

History

The naive approach to computing the visibility of a graph runs in O(n3 ) times. The ﬁrst non-trivial solution to this problem was developed by D.T. Lee in his 1978 Ph.D. dissertation that ran in O(n2 log n) time [9]. The solution is included at the end of his thesis as somewhat of a side thought and it has since then received very little attention in the computational geometry ﬁeld. Only available upon email request, the typed report includes hand-written edits and drawings. This is the algorithm that will be analyzed in this paper. In the 1980’s a large number of O(n2 ) visibility graph papers were published, most of which entailed a topological sort of the vertex pairs. E. Welzl in particular described this technique using an arrangement of the dual of the vertices that required O(n2 ) working space [13]. The working storage of the topological sweep was later improved to O(n) by Edelsbrunner and Guibas [2]. Further improvements included handling dynamic updates of the workspace, using less running time on
FIG. 2: Example of an initialized edge list with all edges that intersect scan line s. Image courtesy of [8]

A second optimally sorted data structure Es is initialized containing all the line segments li ∈ E that intersect scan line s at the start of the algorithm. This operation requires |E | checks, calculating if s and line segment li intersect. The line segments that are found

3 to intersect are inserted into Es with their keys being the distance from c to the intersection point v[i,i−1] such that the root of the sorted data structure always contains the edge closest to c. We can intuitively see that this root edge is the only edge visible from c at this scan line instance. Figure 2 depicts an initialized scan list, though in this example vector s is not horizontal. After the initialization phase the algorithm visits every vertex vi in order of θi in A. The scan line does not have to actually visit every angle in the circle, but only those θi where a vertex vi intersects s. For each vi scanned, the algorithm decides if its corresponding line segment lvi ,vi +1 is the ﬁrst or last vertex seen of its corresponding li . If it is the ﬁrst vertex seen, then lvi ,vi +1 is added to Es and is considered open. If it is the second vertex seen, or if it was initialized as open on s0 , then it is removed from Es and is considered closed. For each visited vi , a check is made to see if vi is the root of Es , signifying that vi is the closest vertex to c with respect to s. If vi has this property, then vi is considered visible and is added to the visibility graph Gv ; otherwise it is obscured by some other edge appearing before it, with respect to c, and is ignored. In this way every visible vertex with respect to c is found and a visibility tree is generated for some vi . This process is repeated n times to build a complete visibility graph.

Finally, the sweeping for-loop begins its check of every vi ∈ V − c points. At each vertex a line is either inserted into or removed from Es once, requiring again O(log n) time for each operation. Thus the total running time for this step is also (n − 1) log n = O(n log n). With these three steps and the outer forloop combined, our summed running time is O(n · (.5n + n + n − 1) · log n), which asymptotically reduces to simply O(n2 log n).

C.

Space Requirements

The space requirements of Lee’s algorithm is analyzed in the following. The input graph G requires O(V + E ) space, but we will assume that the input graph is not included in our space requirements. Two optimum sorting data structures are needed in the algorithm - A and Es . D.T. Lee’s original paper suggested an AVL tree be used; in our implementation we have used a skip list. Regardless, both use O(n) space, totaling 2O(n). Because each θi is inserted into A once, n = |V | for datastructure A. In the worse case all edges are intersected by s at the same time, making Es have size n = |E | = .5|V |. No other memory is used in the algorithm, so the total overall space requirements, not including the input graph, is O(1.5|V |), which is equivalent to simply O(n).

B.

Runtime D. Analysis of Correctness

The asymptotic runtime of Lee’s algorithm is analyzed in the following. The algorithm has four for-loops as well as the operations of the optimal sorting data structure. An outer for-loop iterates once through n = |V | = 2|E | points, ﬁnding the visibility tree for every point. Within the outer for loop, each end point pair for every |E | line segments are inserted into the optimal sorting data structure A. Insert, delete, and ﬁnd all take O(log n) time using a probabilistic structure such as a skip list, or balance binary search tree, such as an AVL tree. Thus, the insertion time for A takes 2|E | log n = O(n log n). Next, the sweep line edge list Es is initialized by checking all |E | edges in G for intersection with s = ˆ i. The edge list Es uses the same data structure as A, and thus all insertions take O(log n) time. In the worse case, all |E | edges intersect s at some θi , so the total runtime for this step is O(|E | log |E |). There are twice as many vertices as edges, and so because |E | < |V |, this runtime is asymptotically overshadowed by the previous step and can be ignored.

We begin our proof of correctness of Lee’s O(n2 log n) algorithm by deﬁning the components of the algorithm. Deﬁnition 1. A visibility graph Gv = (V, Ev ) is the set of all vertices V in input graph G, and the set of edges Ev which connects two vertices vi , vj ∈ V without intersecting any obstacles, for all vi , vj ∈ V . We assume that two endpoints i and j of the same line are also considered visible. We restrict our obstacle set to the |E | disjoint line segments, in any direction. Deﬁnition 2. The line sweep vector s is a vector with its origin at some point c ∈ V that rotates starting from direction ˆ i a full 2π radians. Deﬁnition 3. A line segment li is an obstacle in the 2 dimensional problem space deﬁned between vertices vi and vi−1 . Deﬁnition 4. The set Es contains all li that intersect with s originating at point c, ordered in decreasing Euclidean distance from c to li .

No change is made in the visibility of any line segment with respect to s except when s intersects an end point of some line segments.4 The above deﬁnitions we will now begin to prove the algorithms’ correctness by observing the existence of optimal substructure of the visibility graph: Lemma 1. our lemma stands. An inﬁnitely narrow segment of a directional vector could not be obstructed by more than n = 1 geometric element at a time because otherwise the combined width of n > 1 geometric elements would have to be inﬁnitely small. Proof. A Euclidean vector is deﬁned as a geometric object that has a direction and length (or magnitude). and by contradiction this lemma is proved. The ﬁrst line segment a vector crosses from some point c is the segment closest in Euclidean distance. No more than one obstacle is visible at any time from a center point c with respect to the direction of a scan line vector s at any angle in Euclidean space. The only way to change the visibility of a line segment at s would be to remove the ﬁrst line segment Es because this is the line segment closest to c. We will now expand our proof to all θ ∈ 2π and our discretization method. Given a set of n disjoint line segments in the Euclidean plane. by Lemma 2 we know only one point can have the visible property for a given s. and recalling that at initialization all li in intersection with s are added to Es and marked as open. For N = 1 points. and there are only |V | − 1 endpoints around c so it follows that only |V | − 1 angles of θi need to be checked. The intersection point of s and li ∈ Es with the minimum Euclidean distance to c is the only line segment visible. The mechanism for tracking the removal and insertion of lines into Es is now proved: Lemma 4. We begin by deﬁning the assumptions of our scan line method: Lemma 2.2] . following the same assumption. Otherwise. is a subsolution to ﬁnding the visibility graph of all points vj ∈ V in G. and by the deﬁnition of visibility we know it must be the ﬁrst line segment it reaches. despite having no vi in intersection with s. Assume the set Es correctly contains all line segments that intersect some vector s and assume s is at some θa that does not intersect any end points ∀vi ∈ V . it follows that no point in V will be visible from any other point in V that is not already in the set Ei=1→N . Following the stated assumption that s rotates in a counter clockwise direction.. li must be removed from the set Es (the line was ”open”). In this case our above deﬁnition of a visibility graph is satisﬁed and our N sub-solutions have resulted in correctly ﬁnding the visibility graph Gv for all points vj ∈ V . Proof. Assume the visibility tree Ei for some vi is generated correctly every time. For N = 2 points. but it does not itself have a width. was generated correctly every time. Proof. by the just stated assumption no other endpoint vj of a line segment is visible from that N = 1 point that is not already in the set Ei=1 . Although s may cross several li ∈ Es . for some vertex i. The combined width of two objects would be greater than inﬁnitely small. no changes in visibility occur with respect to the rotation of s around c except when s intersects an end point vi . Proof. because obstacles in our problem space are assumed to be line segments. Suppose we removed this line segment. with respect to the single point vi . Lemma 1 assumed that the set of edges Ei deﬁning a visibility tree. the visibility graph can be constructed correctly in O(n2 log n) time using the rotational sweep method in Lee’s algorithm. or at least the width could be considered inﬁnitely narrow. The utility of a scan line is now suﬃciently proven by Lemma 3 and Corollary 2. By contradiction. that Es must contain all line segments that intersect s. Lemma 3. Then there exists a li that intersects s and Es violates deﬁnition 4 deﬁning what Es must contain. We now prove our algorithm for this subproblem. In the non-discrete angular space θ between 0 and 2π . ˆ i). A line segment li with an end point vi in intersection with s must be added to the set Es if the opposite end point vi−1 of li has not previously been visited (the line was ”closed”). our scan line need only check |V | − 1 discrete steps where θi = angle(sc→vi . Proof. it can be observed that Lemma 4 is required to maintain Deﬁnition 4. Therefore. The visibility tree containing set of all edges Ei connecting a single point vi to all other visible points vj ∈ V − vi . if it has been previously visited. Proof. Using Lemmas 1 to 4 and Corollaries 1 and 2 the following theorem is supported: Theorem 1.
Corollary 2.
Corollary 1.
With Lemma 2 and Corollary 1 we have proved the correctness of the results of scan line s at one θi . no point will be visible to those N = 2 points that is not already in the combined visibility tree set Ei=[1. Following from Lemma 3. For N = |V | points.
.

That is to say. but his paper was published before the invention of skip lists in 1989 by W. 4: Line l1 originally was the closest point to c. RESULTS
Implementation
The O(n2 log n) algorithm was implemented in C++ and visualized/animated using the open source. but in fact there is an additional property that states that the ordering of the items in the skip list are guaranteed not to change. each line segment was represented as an object that could quickly re-calculate its intersection with s and then distance to c. As it is now clear. and for its seconds l2 . With the graphics library we were able to visually verify geometric results such as shown in Figure 3. the scan line would visit the ﬁrst endpoint of l2 and it would add l2 to Es with distance d2 . a unique property of our algorithm required special modiﬁcation to the skip list such that the key values of data already in the skip list are variable. just the values. but at scan line s line l2 covers l1 . cross-platform CImg graphics library. in our current example the ordering of Es would be incorrect at location s unless there was some way to update the value of l1 to reﬂect its distance from c with respect to θi of s . 3: Test input graph of 8 line segments (white) and the generated visibility graph of Ev lines (blue) FIG. In other words. and at scan line s the closest intersecting line segment is now actually l2 . although l1 at angle θi has an intersection with s that is a greater distance than that of l2 from c. Pugh [12]. the value of each element in the skip list changes as the scan line rotates around some center c. Next. Thus. This demonstrates the need for elements variable values in the skip list. In this implementation we chose to use a skip list due to its average case performance and advantage in concurrent access and modiﬁcations.5
IV. Therefore.T.
FIG. However. Skip Lists
D.com/davetcoleman/visibility_graph
line s would visit and so it would be inserted into the skip list Es with the distance d1 from its ﬁrst endpoint to c. the ordering of l1 in Es with respect to all other open line segments in Es would remain unchanged due to the assumption that no line segments can intersect in our problem space. Es would have as its ﬁrst ordered line segment l1 . Lee’s original paper suggested an AVL tree data tree structure be used. A. in implementing the actual visibility graph. In this example line l1 is the ﬁrst line segment that scan
This might seem like an impossible property of a skip list. The full source code is appended at the end of this paper and is available as an open source project online at https: //github. B. This was accomplished by caching the slope m and y-intercept b at the initialization of the
. But by deﬁnition 4. The need for this property is motivated in Figure 4. Es should have as its ﬁrst line segment the segment closest to c.

and average-case for this algorithm because all points are always added to A and E and all points are always visited to generate their individual visibility tree. Our data showed performance that was very tightly bound to a run time of O(n2 log n). in reality only nx = ( (10n )1/2 )2 line segments were added. is mostly due to some memory leaks that were problematic to patch.
D. In the same way. 6: Atomic operations of Lee’s visibility graph algorithm for increasing number of line segments n. 4 shapes were used inside the grids: a horizontal. each line segment was constrained to a grid area. At problem size n = 104 the algorithm crashed on both our laptop and on a node on the Janus super computer. Because of the gridded nature of the problem space. Particularly problematic were perfectly horizontal and vertical lines. with randomly chosen shapes.
FIG. Sometimes two unique points would be added to the angle list A with the same angle because of rounding errors. With vertical lines the slope m would tend to inﬁnity. but in this implementation it was faked with some very large number. However. Which of the 4 was chosen was decided at random. the source code was modiﬁed to automatically generate a set of n line segments.
FIG. This
run time is both the worst. Within each line segment’s grid. With this setup.
Precision Errors
Another issue with our implementation was rounding errors that occurred when calculating the angles between two close points. and the result was that some points were mistakenly added as visible. however. 5: An example generated problem space for nx = ( (10n )1/2 )2 line segments. padding was added to allow more visibility between grids.
Further visual results of the algorithm running for n = 100 line segments is shown in Figure 7 and for n = 1000 line segments in Figure 8. such that every test was run on a problem set with a high probability of being unique. The results of the atomic operations measurements are shown in Figure 6. diagonal increasing and diagonal decreasing line segment.5 . The algorithm was tested for n = 101 → 103. This was especially problematic as we increased the number of line segments added to our ﬁnitely-sized graphics window.6 line object. vertical. An example of an automatically generated problem space is shown in Figure 5.
Numerical Time Usage
To calculate the numerical time usage of this algorithm. To test the runtime with exponentially increasing problem space it was instrumented to generate approximately n = 10x line segments. a horizontal line has a slope with an inﬁnitely small m.
C. Additionally. as well as caching the resultant distance d from c for every θi such that d is only calculated once for every thetai . to ensure a useful test set was generated without intersection. the numerical time usage was measured by counting the number of atomic operations within both the algorithm and the skip lists. This. and this again suﬀered from the limitations of our computer hardware.
.

Lee’s 1978 visibility graph algorithm. the dynamic-valued skip list structure discussed in section IV. Lastly. The results are shown in Figure 9. The upper and lower dotted line bounds are multiplied by constants of 3 and 7. proved and implemented D. As explained in the introduction.
FIG. requires a large number of distance calculations at every rotation of the scan line. In this paper we have explained. the memory usage was on the order of O(n). faster algorithms have been developed that run on O(n2 ) time and other
The numerical space usage of this algorithm was measured by tracking the maximum number of nodes from both skip lists combined at any point in the algorithm. respectively. from the observation that visibility between a pair is mutual. analyzed. B. Other optimizations could be made in the geometric calculations such as studying the performance advantages between ﬁnding the distance using the line-of-sine method versus the intersection method and dealing with slopes of negative and positive inﬁnity. A memory counter was incremented for every new node created. 9: Measured space usage of Lee’s visibility graph algorithm. 8: Generated visibility graph for n = 1000 line segments.T.
E.
Numerical Space Usage
There exists many additional optimization tweaks that could be applied to this algorithm. As expected. and decremented for every node deleted. and could be reduced by only checking a vertices’ change in distance immediately around the skip lists’ chosen insertion point for a new line segment. 7: Generated visibility graph for n = 100 line segments.7 considered to use 3 atomic memory amounts.
V.
FIG. Here. A secondary counter was used to track the maximum amount of memory used at any point in the algorithm’s progress.
CONCLUSIONS
FIG. While simple in explanation. One such optimization is to limit the scan line rotation to only half the circle. such that a root with 3 levels is
. it would be complicated in required modiﬁcation to the skip list algorithm. we deﬁne a node as a level in the skip list structure.