TřiVis: Versatile, Reliable, and High-Performance Tool
for Computing Visibility in Polygonal Environments
Abstract
Visibility is a fundamental concept in computational geometry, with numerous applications in surveillance, robotics, and games. This software paper presents TřiVis, a C++ library developed by the authors for computing numerous visibility-related queries in highly complex polygonal environments. Adapting the triangular expansion algorithm, TřiVis stands out as a versatile, high-performance, more reliable and easy-to-use alternative to current solutions that is also free of heavy dependencies. Through evaluation on a challenging dataset, TřiVis has been benchmarked against existing visibility libraries. The results demonstrate that TřiVis outperforms the competing solutions by at least an order of magnitude in query times, while exhibiting more reliable runtime behavior. TřiVis is freely available for private, research, and institutional use at https://github.com/janmikulacz/trivis.
I Introduction
This software paper presents TřiVis, a C++ library developed by the authors for computing visibility in 2D polygonal environments. The authors, focusing primarily on visibility-based route planning solutions for autonomous mobile robots, have encountered severe limitations in the currently available visibility implementations, including the 2D Visibility package in the widely used Computational Geometry Algorithms Library (CGAL). Motivated by the need for a fast, robust, versatile, and lightweight solution, the authors developed TřiVis to address these limitations and provide a high-performance, reliable, and easy-to-use solution for the robotics community and beyond.
The library is suitable for various applications that involve 2D polygonal environments where frequent visibility queries are essential. These applications include the design of security and surveillance systems [Agarwal2009] and robotics. In the field of robotics, specific examples include route planning for efficient environment inspection or search [Mikula2022, Kulich2022], multi-agent systems [Tokekar2015, Maini2021], and pursuit-evasion games [Lozano2022, Fletcher2023].
This paper is organized as follows: Sec. II defines the fundamental concepts of visibility and related terms. Sec. III provides a literature background on visibility algorithms and describes the primary algorithm used in TřiVis: the triangular expansion algorithm [Bungiu2014, Xu2015]. This section also details the TřiVis-specific adaptations of the algorithm for handling other visibility queries. Sec. IV details the design of TřiVis, including the library’s robustness strategies, internal dependencies, and a short snippet of the library’s usage. Sec. LABEL:sec:performance evaluates the performance of TřiVis on a dataset of complex polygonal environments and compares it with other visibility libraries. Finally, Sec. LABEL:sec:conclusion concludes the paper.
II Definition of Visibility and Related Terms
This section defines the fundamental concepts of visibility and related terms, illustrated with a visual aid in Fig. 1.
Polygonal Environment
A polygonal environment is a 2D region bounded by a single outer boundary and zero or more inner boundaries called holes. More formally, is a non-empty, connected, closed, bounded subset of 2D Euclidean space. The notion of obstacles is implicitly included in the definition of , as represents the entire see-through space, while its complement, , represents the opaque space. Furthermore, all boundaries of are simple polygons: closed, connected series of pairwise non-intersecting line segments. We denote the set of all these segments, united from all the boundaries, as the edges of , with endpoints referred to as the vertices of .
Convex Polygonal / Triangular Mesh
Any polygonal environment can be represented non-uniquely as a convex polygonal mesh , consisting of convex polygons such that their union forms , and the intersection of any two polygons is either empty, a single point, or a single line segment. We denote the set of all edges formed by the polygons as the edges of , with endpoints referred to as the vertices of . Unless specified otherwise, we assume that no additional vertices have been added to , i.e., . Moreover, we consider a structure called a convex polygonal graph, which encapsulates along with the topological relationships such as adjacency between the polygons, edges, and vertices. For simplicity, the convex polygonal graph is denoted by the same symbol as its corresponding convex polygonal mesh. The process of constructing from is called convex partitioning. A special instance of the convex polygonal mesh is one in which all polygons are triangles. Both the triangular mesh and its corresponding triangular graph are denoted as . The process of constructing from is called triangulation.
Point Location Query
This query is not necessarily related to visibility but is essential for the operation of TřiVis. It involves determining the location of a point with respect to , , or . The usual objective is to determine whether lies inside or outside , and if it lies inside, whether it coincides with one of the vertices or lies on a specific edge . For and , the objective is similar, but an additional goal is to identify the polygon or triangle, respectively, that contains .
Two-Points Visibility Query
Two points are said to be visible to each other if the line segment lies entirely within , i.e., . The query definition is as follows: Given , determine whether .
Ray Shooting
This visibility-related query aims to find the first intersection point of a half-line, called a ray, with the boundary of . Given a point and a directional vector , which defines the ray, the objective is to find the point , where is the boundary of . Note that is always defined because is a closed, bounded region, while the ray starts inside and extends indefinitely. Additionally, the above expression implies that and are visible to each other, i.e., .
Visibility Region / Polygon
The visibility region is the set of all points visible from a given point , defined as . In polygonal environments, visibility regions take the form of polygons. These polygons are usually simple, except in cases where one-dimensional structures, known as antennas, are created. Antennas occur when the query point aligns with two vertices of the environment, restricting visibility from opposite sides.
Visible Points / Vertices Query
The visible points query aims to identify a subset of a given finite set of points that are visible from a given query point . Its definition resembles that of the visibility region, but the output domain is confined to : . In polygonal environments, we can consider a special case of the visible points query, called the visible vertices query, where . We denote the output in this case as .
Visibility Graph / Subgraphs
The visibility graph is a structure used to represent the pairwise visibility relationships among a given finite set of points . It is defined as a simple undirected graph , where and are the vertex and edge sets, respectively. In polygonal environments, we can classify three types of visibility subgraphs by writing the set of visibility graph query points as , where is a set of vertices, is a set of non-vertex points, and . Then, the vertex-vertex visibility graph, denoted as , is the subgraph of induced by . The point-point visibility graph, denoted as , is the subgraph of induced by . Lastly, the vertex-point visibility graph is defined as , where and . Note the following relationships: , , , and .
Limited Visibility
Visibility may be subject to additional constraints. In particular, we can consider a limited visibility range : two points and in are considered -visible to each other if the line segment lies entirely within and has a length no greater than , i.e., . The set of all points -visible from a given point is called the -visibility region and is defined as . Note that the -visibility region may no longer be a polygon, as it may contain circular arcs due to the limited visibility range. Similarly, we could define the -visibility graph, -visible points query, or -visibility ray shooting (with a Null result if ).
III Visibility Algorithms
This paper does not introduce new algorithms, nor does it aim to offer an exhaustive review of existing visibility algorithms for all queries defined in Sec. II. Instead, the presented library is centered around the triangular expansion algorithm (TEA), which has been adapted to handle all these visibility queries in polygonal environments. To provide a partial background, we present a literature review of algorithms for computing visibility polygons in Sec. III-A. Following this, the TEA is elaborated upon in Sec. III-B, and the section concludes with a description of the TřiVis-specific adaptations for handling other queries in Sec. III-C.
III-A Literature Background on Visibility Polygons
Computing visibility polygons is a well-explored area within computational geometry originating in the late 1970s [Davis1979]. Since then, it has received continuous attention from numerous researchers, primarily focusing on the theoretically proven complexity of the algorithms rather than their practical implementation and experimental validation. Initially, the emphasis was on simple polygons, aiming to reduce the query time to , where denotes the number of vertices in the polygon. The first correct solution was proposed by Joe and Simpson [Joe1987].
Subsequently, attention shifted towards polygons with holes until Heffernan and Mitchell [Heffernan1995] introduced the optimal algorithm, where signifies the number of holes, surpassing the previously leading -time rotational sweep algorithm (RSA) by Asano [Asano1985]. In subsequent decades, numerous algorithms emerged for polygons with holes, offering diverse trade-offs between preprocessing time and query time. For example, Zarei and Ghodsi [Zarei2008] presented an algorithm with preprocessing time and query time; Inkulu and Kapoor [Inkulu2009] introduced a method with preprocessing time and query time; and Chen and Wang [Chen2015] devised an approach with preprocessing time and query time.
As previously mentioned, the research discussed thus far has primarily focused on theoretical aspects, with limited attention given to practical implementation, creating a notable gap in the field. This gap was addressed by Bungiu et al. [Bungiu2014], who implemented Joe and Simpson’s algorithm for simple polygons [Joe1987] and Asano’s RSA for polygons with holes [Asano1985] within the then-new CGAL 2D Visibility package.
Since the remaining algorithms presented in the literature were deemed too complex for practical implementation, Bungiu et al. [Bungiu2014] also introduced their own solution, the TEA, which they integrated into the same package. Although the TEA, with a worst-case query time of , does not rank among the theoretically fastest algorithms, the authors demonstrated that it performs two orders of magnitude faster than the RSA in real-world scenarios, establishing it as the favored algorithm for computing visibility polygons in practice. Although Bungiu et al.’s work is significant, we faced several difficulties while using the CGAL 2D Visibility package for our research, which motivated the development of TřiVis. These difficulties are apparent from our evaluation of the package in Sec. LABEL:sec:performance.
It is worth noting that Xu and Güting [Xu2015] independently111 Xu and Güting’s manuscript was submitted for publication nearly six months before Bungiu et al.’s manuscript appeared on ArXiv, which, to our knowledge, remains unpublished. Therefore, it is highly likely that these two independent research groups were unaware of each other’s work. developed an equivalent algorithm to the TEA for the visible vertices query. However, their work has received little to no attention compared to Bungiu et al.’s [Bungiu2014], as evidenced by the Google Scholar citation count.
III-B Triangular Expansion Algorithm
We base our description on [Bungiu2014], as computing visibility polygons is more relevant to our evaluation in Sec. LABEL:sec:performance. The following description assumes that the input polygonal environment has been triangulated into and that the query point has been located inside a triangle .
Basic Idea and Features
The underlying idea is simple: The TEA computes the visibility polygon by recursively traversing neighboring triangles, starting from . The first notable feature is that it exclusively traverses triangles visible from the query point, making it output-sensitive to some extent. However, it may also traverse triangles that do not contribute directly to the boundary of the resulting visibility polygon [Bungiu2014], rendering it only partially output-sensitive. The second significant feature is the simplicity of the operations during mesh traversal. These operations essentially involve answering two orientation predicates per triangle traversal and computing at most two ray-segment intersections when encountering an edge of .
Detailed Operation of the TEA
Starting at , a recursive expansion procedure is initiated for each of its edges, gradually forming a set of restricted views around .222 An animated visualization of the TEA operation is available at https://www.youtube.com/watch?v=gKSA6lxVTKw. The recursive procedure expands along the current edge to the neighboring triangle, restricting the view from between the edge’s endpoints. In the new triangle, the other two edges are considered as candidates for the next recursion call only if they intersect the current restricted view from . The new recursion call is eventually initiated for any of those candidate edges that neighbor another triangle. Otherwise, the edge is identified as a boundary edge of , and the current view from is ultimately restricted between its endpoints, stored, and the recursion does not propagate further from that point. Once no further expansions are possible, the resulting is the union of all the restricted views formed around . Additionally, an efficient TEA implementation takes advantage of pre-ordering the neighbor information in either clockwise (cw) or counterclockwise (ccw) order. The expansions then rotate around while adhering to the same order, naturally forming the union of the restricted views.
Vertex Query
When the query point coincides with one of the mesh vertices, a special case arises where the TEA must consider the union of all triangles incident to that vertex. This union forms the basis of the resulting visibility polygon, similarly to the initial triangle in the general case. The expansion procedure is initiated for each outer edge of that union, where an outer edge is defined as an edge that is not shared with another triangle in the union. Otherwise, the operation is identical to the one described above.
Complexity Analysis
As stated by Bungiu et al. [Bungiu2014], the worst-case query time is , where . This is because the recursion may split into two views times, and each view may reach triangles. However, splits into two views that independently reach the same triangle may only occur at the holes of . This implies that the worst-case query time is rather .333 The possibility for two independent views to reach the same triangle by splitting at a hole is an essential property of the TEA, which seems to not have been realized by the other independent authors of the TEA, Xu and Güting [Xu2015]. Therefore, their complexity analysis, which states the worst-case query time to be , is incorrect.
Preprocessing
When the input for the TEA is not the triangular mesh , but instead the polygonal environment or the convex polygonal mesh , the TEA query phase must be preceded by the respective preprocessing phase. The preprocessing involves the triangulation of or individual polygons in . For example, this can be achieved by the constrained Delaunay triangulation (CDT), for which exist algorithms running in [Chew1987] time.
Optimal Mesh
TEA authors have not examined how the choice of triangular mesh affects the query performance of the TEA. To fill this gap, we address this issue in our prior research [Mikula2024], where we derive the optimal triangular mesh under the assumption that query points are uniformly distributed over . Unfortunately, constructing this optimal mesh involves solving an NP-hard problem. Thus, we propose a parametric heuristic approach that balances mesh quality and preprocessing time. We assess the TEA’s performance with the approximate optimal mesh, denoted as MinVT, on a dataset of complex polygonal environments (the same dataset as used in this paper) and compare it with the performance of the TEA with CDT. Our experiments show that the MinVT mesh can improve the query time by 12–16% compared to CDT, at the expense of 9–212 seconds of preprocessing, depending on the chosen parametrization. While this improvement may not meet our initial expectations, it is still significant enough to justify the use of the MinVT mesh in applications where preprocessing time is not a critical factor. However, for simplicity, in this paper, we opt for the CDT mesh.
III-C Adaptations for the Other Visibility Queries
In TřiVis, the TEA is the primary algorithm for computing visibility in polygonal environments. Initially, the library was developed to compute visibility polygons but has since been adapted to handle other visibility queries from Sec. II. A brief overview of these adaptations follows.
Adapting the TEA for the visible vertices query involves a straightforward modification, where the output is now a collection of the traversed triangles’ vertices visible from the query point . Furthermore, there is no need to compute any intersections with the boundary of , which reduces the computational effort. The visible points query follows a similar process, but it requires precomputed point location queries with respect to for the input set of points . These input points are then stored within the corresponding triangle containing them. During the query phase, the algorithm looks up the stored points for each traversed triangle and assesses whether they fall within the current restricted view from the query point. The subset of containing points that have been visible at some point during the traversal is returned as the output at the end of the expansion procedure.
In the context of the two-points visibility query, we denote one of the query points as the source and the other as the target . Similar to other queries, TřiVis initiates the expansion from . However, unlike the previously mentioned queries, it does not need to expand in all directions; rather, it expands directly towards . This means that only triangles along the line segment are traversed, which implies that no views are split at holes and the worst-case query time is for this query. If the target is reached before encountering the boundary of , indicating that the target is visible from the source, the algorithm returns true; otherwise, it returns false. By adjusting this approach, we can derive the ray-shooting query, where no target is considered, and only the direction vector guides the expansions. In this case, the expansion procedure terminates as soon as the first intersection with the boundary of is found, and the intersection point is returned.
Computing the visibility graph for a set of query points is a more complex task, as it involves computing the three types of visibility subgraphs and, if desired, merging them into a single graph. For the vertex-vertex and vertex-point visibility graph, the visible vertices query is executed for each vertex in and each point in , respectively. For the point-point visibility graph, the visible points query is executed for each point in .
TřiVis can also handle -visibility queries by incorporating as an additional input to the TEA, resulting in a variant we denote as d-TEA. A branch of the d-TEA’s expansion procedure terminates prematurely if the distance from the query point to the edge being expanded exceeds . This can significantly reduce the number of traversed triangles, especially for small values of relative to the expected distance between two points in that are visible to each other. To ensure correctness, the query outputs are also adjusted to account for the distance constraint, typically involving straightforward distance checks between the query point and the output points. The most complex case arises with the -visibility region, where the output of the expansion procedure, , is a superset of the correct result, , and the final output is obtained by intersecting with a circle centered at the query point with radius .
IV Library Design and Usage
This section outlines TřiVis’s design, covering robustness strategies (Sec. IV-A), the visibility query scheme (Sec. IV-B), and point location implementation (Sec. IV-C). We also review the library’s internal dependencies in Sec. IV-D and provide a usage code snippet in Sec. IV-E.
IV-A Robustness Strategies
TřiVis relies on floating-point arithmetic and incorporates a unique combination of adaptive robust geometry predicates [RichardShewchuk1997] and -geometry [Fortune1993]. The predicates are employed in TřiVis’s expansion procedure, ensuring consistent answers to orientation queries. This prevents the algorithm from encountering infinite loops and considerably enhances its performance compared to using the non-adaptive versions [RichardShewchuk1997].
Additionally, -geometry is employed to address persistent issues despite the utilization of robust predicates. In particular, we have encountered the following two issues during the development of TřiVis. First, due to numerical inaccuracies, computing the correct intersection points for visibility queries when the query point is near some vertex of has been difficult. To address this, we implemented the so-called vertex snapping technique controlled by the value, as described in Sec. IV-B.
Second, we faced instances where the robust predicates failed to determine that a point lies on a triangle edge, despite the point being computed as the midpoint of that edge. For example, considering triangle vertices represented as vectors and , with computed as in floating-point representation, the robust geometric predicates indicate that lies outside the triangle in high percentage of cases. While this behavior is not necessarily a problem of the robust predicates themselves, it is likely undesirable from the user’s perspective. To mitigate this issue, we implemented the point location query as a combination of exact and inexact arithmetic, as described in Sec. IV-B, where the inexact arithmetic is controlled by a sequence of increasing values.
IV-B General Scheme for Answering Visibility Queries
The TřiVis library consists of a set of C++ classes and functions, with its primary class being Trivis. This class serves as the core of the library, responsible for executing visibility queries, managing query input and output, and preprocessing the polygonal environment. Query execution relies on the TEA and its adaptations, detailed in Sec. III-B and Sec. III-C, respectively, and follows a generic scheme outlined in Alg. 1.
Each visibility query requires the query point as mandatory input, except for visibility graphs, which are constructed through multiple calls to this type of query function. Additionally, the query function accepts specific arguments depending on the query type, such as the target point for the two-points visibility query, directional vector for the ray-shooting query, and the set of points for the visible points query, or the distance for all the -visibility queries. The query function also accepts a set of values (a sequence and a single ), which enhance the robustness and control the behavior of the query. The motivation behind these values is discussed in Sec. IV-A; here, we focus on the precise logic of their usage.
The generic query function in Alg. 1 first attempts to find the triangle containing using the robust geometric predicates (line 2). If this fails, it resorts to -geometry, employing the sequence of increasing values to locate (lines 3–7). If is still not found, it is interpreted that lies outside , and the function returns Null (line 5) to indicate this. If is found, the function checks whether is near any vertices of using the value (lines 8–9). If so, the vertex query is executed (line 10), expanding all outer edges of the union of triangles incident to the vertex. When and , the operation at lines 8–10 can be interpreted as vertex snapping, where is snapped to . Otherwise, the standard expansion procedure is initiated, expanding all edges of . The procedure is recursive, and the function returns the query output once it eventually terminates (line 10 or 11).
IV-C Bucketing for Point Location
The point location query identifies the triangle containing the query point, which is the first step of Alg. 1. In TřiVis, we implement the bucketing technique from [Edahiro1984] to achieve an average time complexity of . This technique preprocesses the triangular mesh by subdividing the bounding box of into square cells called buckets, each storing the triangles intersecting it. During the query phase, the bucket containing the query point is found by rounding the point’s coordinates. Finally, the bucket’s triangles undergo the point-in-triangle test, resulting in the identification of triangle . The test is performed exactly using the robust predicates at line 2 of Alg. 1, and using the values at line 7.
IV-D Internal Dependencies
TřiVis, implemented in C++17, is self-contained, ensuring that its core functionality is independent of external libraries. However, internally, it depends on some third-party software that is freely available for private, research, and institutional use, and is integrated into the library’s source code. Most importantly, TřiVis relies on Robust-Predicate444Available at https://github.com/dengwirda/robust-predicate. for the adaptive robust geometry predicates, and Triangle555Available at https://www.cs.cmu.edu/~quake/triangle.html. [Shewchuk1996, Shewchuk2002] for computing triangular meshes. Furthermore, Clipper2666Available at https://github.com/AngusJohnson/Clipper2. is integrated for polygon-related operations such as clipping and offsetting. Although the core functionality of TřiVis does not necessarily require Clipper2, it is utilized in the library’s evaluation in Sec. LABEL:sec:performance. The remaining core functionality of TřiVis, as outlined in this paper, represents original contributions from the authors.
IV-E Library Usage
TřiVis offers a user-friendly interface through the Trivis class for executing all the visibility queries defined in Sec. II. Fig. LABEL:fig:code_snippet shows a code snippet for computing a -visibility region from a query point . This snippet is simplified for brevity and requires the user to provide the environment data, the query point, and set the visibility range (the latter two have default values). The output is a polygonal approximation of the -visibility region, with circular arcs sampled using line segments at an angle no greater than . For detailed usage and complete example projects, including visualization, refer to the library’s README.md on the GitHub repository at https://github.com/janmikulacz/trivis.