TřiVis: Versatile, Reliable, and High-Performance Tool
for Computing Visibility in Polygonal Environments

Jan Mikula1,2, Miroslav Kulich1, and Libor Přeučil1 This work was co-funded by the European Union under the project Robotics and advanced industrial production (reg. no. CZ.02.01.01/00/22_008/0004590) and by the Grant Agency of the Czech Technical University in Prague, grant no. SGS23/175/OHK3/3T/13. 1All authors are with the Czech Institute of Informatics, Robotics and Cybernetics, Czech Technical University in Prague, Jugoslavskych partyzanu 1580/3, Prague 6, 160 00, Czech Republic. {jan.mikula, miroslav.kulich, libor.preucil}@cvut.cz2Jan Mikula is also with the Department of Cybernetics, Faculty of Electrical Engineering, Czech Technical University in Prague, Karlovo namesti 293/13, Prague 2, 121 35, Czech Republic.
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.

Refer to caption
(a)
Refer to caption
(b)
Refer to caption
(c)
Refer to caption
(d)
Refer to caption
(e)
Refer to caption
(f)
Refer to caption
(g)
Refer to caption
(h)
Refer to caption
(i)
Figure 1: Different visibility queries in the same polygonal environment. From left to right, first row: two-points visibility, ray-shooting, visibility polygon. Second row: d𝑑ditalic_d-visibility region, visible vertices, d𝑑ditalic_d-visible vertices. Third row: vertex-vertex visibility graph, point-point visibility graph, vertex-point visibility graph.

Polygonal Environment

A polygonal environment 𝒲𝒲\mathcal{W}caligraphic_W is a 2D region bounded by a single outer boundary and zero or more inner boundaries called holes. More formally, 𝒲𝒲\mathcal{W}caligraphic_W is a non-empty, connected, closed, bounded subset of 2D Euclidean space. The notion of obstacles is implicitly included in the definition of 𝒲𝒲\mathcal{W}caligraphic_W, as 𝒲𝒲\mathcal{W}caligraphic_W represents the entire see-through space, while its complement, 2𝒲superscript2𝒲\mathbb{R}^{2}{\,\setminus\,}\mathcal{W}blackboard_R start_POSTSUPERSCRIPT 2 end_POSTSUPERSCRIPT ∖ caligraphic_W, represents the opaque space. Furthermore, all boundaries of 𝒲𝒲\mathcal{W}caligraphic_W 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 E𝒲subscript𝐸𝒲E_{\mathcal{W}}italic_E start_POSTSUBSCRIPT caligraphic_W end_POSTSUBSCRIPT of 𝒲𝒲\mathcal{W}caligraphic_W, with endpoints referred to as the vertices V𝒲subscript𝑉𝒲V_{\mathcal{W}}italic_V start_POSTSUBSCRIPT caligraphic_W end_POSTSUBSCRIPT of 𝒲𝒲\mathcal{W}caligraphic_W.

Convex Polygonal / Triangular Mesh

Any polygonal environment 𝒲𝒲\mathcal{W}caligraphic_W can be represented non-uniquely as a convex polygonal mesh 𝒞𝒞\mathcal{C}caligraphic_C, consisting of convex polygons such that their union forms 𝒲𝒲\mathcal{W}caligraphic_W, 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 E𝒞subscript𝐸𝒞E_{\mathcal{C}}italic_E start_POSTSUBSCRIPT caligraphic_C end_POSTSUBSCRIPT of 𝒞𝒞\mathcal{C}caligraphic_C, with endpoints referred to as the vertices V𝒞subscript𝑉𝒞V_{\mathcal{C}}italic_V start_POSTSUBSCRIPT caligraphic_C end_POSTSUBSCRIPT of 𝒞𝒞\mathcal{C}caligraphic_C. Unless specified otherwise, we assume that no additional vertices have been added to 𝒞𝒞\mathcal{C}caligraphic_C, i.e., V𝒞=V𝒲subscript𝑉𝒞subscript𝑉𝒲V_{\mathcal{C}}{\,=\,}V_{\mathcal{W}}italic_V start_POSTSUBSCRIPT caligraphic_C end_POSTSUBSCRIPT = italic_V start_POSTSUBSCRIPT caligraphic_W end_POSTSUBSCRIPT. Moreover, we consider a structure called a convex polygonal graph, which encapsulates 𝒞𝒞\mathcal{C}caligraphic_C 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 𝒞𝒞\mathcal{C}caligraphic_C as its corresponding convex polygonal mesh. The process of constructing 𝒞𝒞\mathcal{C}caligraphic_C from 𝒲𝒲\mathcal{W}caligraphic_W 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 𝒯𝒯\mathcal{T}caligraphic_T. The process of constructing 𝒯𝒯\mathcal{T}caligraphic_T from 𝒲𝒲\mathcal{W}caligraphic_W 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 q2𝑞superscript2q{\,\in\,}\mathbb{R}^{2}italic_q ∈ blackboard_R start_POSTSUPERSCRIPT 2 end_POSTSUPERSCRIPT with respect to 𝒲𝒲\mathcal{W}caligraphic_W, 𝒞𝒞\mathcal{C}caligraphic_C, or 𝒯𝒯\mathcal{T}caligraphic_T. The usual objective is to determine whether q𝑞qitalic_q lies inside or outside 𝒲𝒲\mathcal{W}caligraphic_W, and if it lies inside, whether it coincides with one of the vertices vV𝒲𝑣subscript𝑉𝒲v{\,\in\,}V_{\mathcal{W}}italic_v ∈ italic_V start_POSTSUBSCRIPT caligraphic_W end_POSTSUBSCRIPT or lies on a specific edge eE𝒲𝑒subscript𝐸𝒲e{\,\in\,}E_{\mathcal{W}}italic_e ∈ italic_E start_POSTSUBSCRIPT caligraphic_W end_POSTSUBSCRIPT. For 𝒞𝒞\mathcal{C}caligraphic_C and 𝒯𝒯\mathcal{T}caligraphic_T, the objective is similar, but an additional goal is to identify the polygon or triangle, respectively, that contains q𝑞qitalic_q.

Two-Points Visibility Query

Two points q,p𝒲𝑞𝑝𝒲q,p{\,\in\,}\mathcal{W}italic_q , italic_p ∈ caligraphic_W are said to be visible to each other if the line segment qp¯¯𝑞𝑝\overline{qp}over¯ start_ARG italic_q italic_p end_ARG lies entirely within 𝒲𝒲\mathcal{W}caligraphic_W, i.e., qp¯𝒲¯𝑞𝑝𝒲\overline{qp}{\,\subset\,}\mathcal{W}over¯ start_ARG italic_q italic_p end_ARG ⊂ caligraphic_W. The query definition is as follows: Given q,p𝒲𝑞𝑝𝒲q,p{\,\in\,}\mathcal{W}italic_q , italic_p ∈ caligraphic_W, determine whether qp¯𝒲¯𝑞𝑝𝒲\overline{qp}{\,\subset\,}\mathcal{W}over¯ start_ARG italic_q italic_p end_ARG ⊂ caligraphic_W.

Ray Shooting

This visibility-related query aims to find the first intersection point of a half-line, called a ray, with the boundary of 𝒲𝒲\mathcal{W}caligraphic_W. Given a point q𝒲𝑞𝒲q{\,\in\,}\mathcal{W}italic_q ∈ caligraphic_W and a directional vector un𝑢superscript𝑛u{\,\in\,}\mathbb{R}^{n}italic_u ∈ blackboard_R start_POSTSUPERSCRIPT italic_n end_POSTSUPERSCRIPT, which defines the ray, the objective is to find the point p=argminλ 0{q+λuq+λu𝒲}𝑝subscriptargmin𝜆 0𝑞conditional𝜆𝑢𝑞𝜆𝑢𝒲p{\,=\,}\operatorname*{arg\,min}_{\lambda{\,\geq\,}0}\{q{\,+\,}\lambda u{\,% \mid\,}q{\,+\,}\lambda u{\,\in\,}\partial\mathcal{W}\}italic_p = start_OPERATOR roman_arg roman_min end_OPERATOR start_POSTSUBSCRIPT italic_λ ≥ 0 end_POSTSUBSCRIPT { italic_q + italic_λ italic_u ∣ italic_q + italic_λ italic_u ∈ ∂ caligraphic_W }, where 𝒲𝒲\partial\mathcal{W}∂ caligraphic_W is the boundary of 𝒲𝒲\mathcal{W}caligraphic_W. Note that p𝑝pitalic_p is always defined because 𝒲𝒲\mathcal{W}caligraphic_W is a closed, bounded region, while the ray starts inside 𝒲𝒲\mathcal{W}caligraphic_W and extends indefinitely. Additionally, the above expression implies that q𝑞qitalic_q and p𝑝pitalic_p are visible to each other, i.e., qp¯𝒲¯𝑞𝑝𝒲\overline{qp}{\,\subset\,}\mathcal{W}over¯ start_ARG italic_q italic_p end_ARG ⊂ caligraphic_W.

Visibility Region / Polygon

The visibility region is the set of all points visible from a given point q𝑞qitalic_q, defined as 𝒱(q)={p𝒲qp¯𝒲}𝒱𝑞conditional-set𝑝𝒲¯𝑞𝑝𝒲\mathcal{V}(q){\,=\,}\{p{\,\in\,}\mathcal{W}{\,\mid\,}\overline{qp}{\,\subset% \,}\mathcal{W}\}caligraphic_V ( italic_q ) = { italic_p ∈ caligraphic_W ∣ over¯ start_ARG italic_q italic_p end_ARG ⊂ caligraphic_W }. 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 P𝒲𝑃𝒲P{\,\subset\,}\mathcal{W}italic_P ⊂ caligraphic_W that are visible from a given query point q𝒲𝑞𝒲q{\,\in\,}\mathcal{W}italic_q ∈ caligraphic_W. Its definition resembles that of the visibility region, but the output domain is confined to P𝑃Pitalic_P: 𝒱P(q)={pPqp¯𝒲}subscript𝒱𝑃𝑞conditional-set𝑝𝑃¯𝑞𝑝𝒲\mathcal{V}_{P}(q){\,=\,}\{p{\,\in\,}P{\,\mid\,}\overline{qp}{\,\subset\,}% \mathcal{W}\}caligraphic_V start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT ( italic_q ) = { italic_p ∈ italic_P ∣ over¯ start_ARG italic_q italic_p end_ARG ⊂ caligraphic_W }. In polygonal environments, we can consider a special case of the visible points query, called the visible vertices query, where PV𝒲𝑃subscript𝑉𝒲P{\,\subset\,}V_{\mathcal{W}}italic_P ⊂ italic_V start_POSTSUBSCRIPT caligraphic_W end_POSTSUBSCRIPT. We denote the output in this case as 𝒱V(q)subscript𝒱𝑉𝑞\mathcal{V}_{V}(q)caligraphic_V start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT ( italic_q ).

Visibility Graph / Subgraphs

The visibility graph is a structure used to represent the pairwise visibility relationships among a given finite set of points Q𝒲𝑄𝒲Q{\,\subset\,}\mathcal{W}italic_Q ⊂ caligraphic_W. It is defined as a simple undirected graph GQ=(VQ,EQ)subscript𝐺𝑄subscript𝑉𝑄subscript𝐸𝑄G_{Q}{\,=\,}(V_{Q},E_{Q})italic_G start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT = ( italic_V start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT , italic_E start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT ), where VQ=Qsubscript𝑉𝑄𝑄V_{Q}{\,=\,}Qitalic_V start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT = italic_Q and EQ={{q,p}q,pQqpqp¯𝒲}subscript𝐸𝑄conditional-set𝑞𝑝𝑞𝑝𝑄𝑞𝑝¯𝑞𝑝𝒲E_{Q}{\,=\,}\{\{q,p\}{\,\mid\,}q,p{\,\in\,}Q{\,\land\,}q{\,\neq\,}p{\,\land\,}% \overline{qp}{\,\subset\,}\mathcal{W}\}italic_E start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT = { { italic_q , italic_p } ∣ italic_q , italic_p ∈ italic_Q ∧ italic_q ≠ italic_p ∧ over¯ start_ARG italic_q italic_p end_ARG ⊂ caligraphic_W } 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 Q=VP𝑄𝑉𝑃Q{\,=\,}V{\,\cup\,}Pitalic_Q = italic_V ∪ italic_P, where VV𝒲𝑉subscript𝑉𝒲V{\,\subset\,}V_{\mathcal{W}}italic_V ⊂ italic_V start_POSTSUBSCRIPT caligraphic_W end_POSTSUBSCRIPT is a set of vertices, PV𝒲𝑃subscript𝑉𝒲P{\,\subset\,}V_{\mathcal{W}}italic_P ⊂ italic_V start_POSTSUBSCRIPT caligraphic_W end_POSTSUBSCRIPT is a set of non-vertex points, and VP=𝑉𝑃V{\,\cap\,}P{\,=\,}\emptysetitalic_V ∩ italic_P = ∅. Then, the vertex-vertex visibility graph, denoted as GV=(VV,EV)subscript𝐺𝑉subscript𝑉𝑉subscript𝐸𝑉G_{V}{\,=\,}(V_{V},E_{V})italic_G start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT = ( italic_V start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT , italic_E start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT ), is the subgraph of GQsubscript𝐺𝑄G_{Q}italic_G start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT induced by V𝑉Vitalic_V. The point-point visibility graph, denoted as GP=(VP,EP)subscript𝐺𝑃subscript𝑉𝑃subscript𝐸𝑃G_{P}{\,=\,}(V_{P},E_{P})italic_G start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT = ( italic_V start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT , italic_E start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT ), is the subgraph of GQsubscript𝐺𝑄G_{Q}italic_G start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT induced by P𝑃Pitalic_P. Lastly, the vertex-point visibility graph is defined as GVP=(VVP,EVP)subscript𝐺𝑉𝑃subscript𝑉𝑉𝑃subscript𝐸𝑉𝑃G_{V\!P}{\,=\,}(V_{V\!P},E_{V\!P})italic_G start_POSTSUBSCRIPT italic_V italic_P end_POSTSUBSCRIPT = ( italic_V start_POSTSUBSCRIPT italic_V italic_P end_POSTSUBSCRIPT , italic_E start_POSTSUBSCRIPT italic_V italic_P end_POSTSUBSCRIPT ), where VVP=VQsubscript𝑉𝑉𝑃subscript𝑉𝑄V_{V\!P}{\,=\,}V_{Q}italic_V start_POSTSUBSCRIPT italic_V italic_P end_POSTSUBSCRIPT = italic_V start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT and EVP=EQEVEPsubscript𝐸𝑉𝑃subscript𝐸𝑄subscript𝐸𝑉subscript𝐸𝑃E_{V\!P}{\,=\,}E_{Q}{\,\setminus\,}E_{V}{\,\setminus\,}E_{P}italic_E start_POSTSUBSCRIPT italic_V italic_P end_POSTSUBSCRIPT = italic_E start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT ∖ italic_E start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT ∖ italic_E start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT. Note the following relationships: VQ=VVP=VVVPsubscript𝑉𝑄subscript𝑉𝑉𝑃subscript𝑉𝑉subscript𝑉𝑃V_{Q}{\,=\,}V_{V\!P}{\,=\,}V_{V}{\,\cup\,}V_{P}italic_V start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT = italic_V start_POSTSUBSCRIPT italic_V italic_P end_POSTSUBSCRIPT = italic_V start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT ∪ italic_V start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT, VVVP=subscript𝑉𝑉subscript𝑉𝑃V_{V}{\,\cap\,}V_{P}{\,=\,}\emptysetitalic_V start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT ∩ italic_V start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT = ∅, EQ=EVEPEVPsubscript𝐸𝑄subscript𝐸𝑉subscript𝐸𝑃subscript𝐸𝑉𝑃E_{Q}{\,=\,}E_{V}{\,\cup\,}E_{P}{\,\cup\,}E_{V\!P}italic_E start_POSTSUBSCRIPT italic_Q end_POSTSUBSCRIPT = italic_E start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT ∪ italic_E start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT ∪ italic_E start_POSTSUBSCRIPT italic_V italic_P end_POSTSUBSCRIPT, and EVEP=EVEVP=EPEVP=subscript𝐸𝑉subscript𝐸𝑃subscript𝐸𝑉subscript𝐸𝑉𝑃subscript𝐸𝑃subscript𝐸𝑉𝑃E_{V}{\,\cap\,}E_{P}{\,=\,}E_{V}{\,\cap\,}E_{V\!P}{\,=\,}E_{P}{\,\cap\,}E_{V\!% P}{\,=\,}\emptysetitalic_E start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT ∩ italic_E start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT = italic_E start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT ∩ italic_E start_POSTSUBSCRIPT italic_V italic_P end_POSTSUBSCRIPT = italic_E start_POSTSUBSCRIPT italic_P end_POSTSUBSCRIPT ∩ italic_E start_POSTSUBSCRIPT italic_V italic_P end_POSTSUBSCRIPT = ∅.

Limited Visibility

Visibility may be subject to additional constraints. In particular, we can consider a limited visibility range d𝑑ditalic_d: two points q𝑞qitalic_q and p𝑝pitalic_p in 𝒲𝒲\mathcal{W}caligraphic_W are considered d𝑑ditalic_d-visible to each other if the line segment qp¯¯𝑞𝑝\overline{qp}over¯ start_ARG italic_q italic_p end_ARG lies entirely within 𝒲𝒲\mathcal{W}caligraphic_W and has a length no greater than d𝑑ditalic_d, i.e., qp¯𝒲qp¯d¯𝑞𝑝𝒲norm¯𝑞𝑝𝑑\overline{qp}{\,\subset\,}\mathcal{W}{\,\land\,}\|\overline{qp}\|{\,\leq\,}dover¯ start_ARG italic_q italic_p end_ARG ⊂ caligraphic_W ∧ ∥ over¯ start_ARG italic_q italic_p end_ARG ∥ ≤ italic_d. The set of all points d𝑑ditalic_d-visible from a given point q𝑞qitalic_q is called the d𝑑ditalic_d-visibility region and is defined as 𝒱d(q)={p𝒲qp¯𝒲qp¯d}subscript𝒱𝑑𝑞conditional-set𝑝𝒲¯𝑞𝑝𝒲norm¯𝑞𝑝𝑑\mathcal{V}_{d}(q){\,=\,}\{p{\,\in\,}\mathcal{W}{\,\mid\,}\overline{qp}{\,% \subset\,}\mathcal{W}{\,\land\,}\|\overline{qp}\|{\,\leq\,}d\}caligraphic_V start_POSTSUBSCRIPT italic_d end_POSTSUBSCRIPT ( italic_q ) = { italic_p ∈ caligraphic_W ∣ over¯ start_ARG italic_q italic_p end_ARG ⊂ caligraphic_W ∧ ∥ over¯ start_ARG italic_q italic_p end_ARG ∥ ≤ italic_d }. Note that the d𝑑ditalic_d-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 d𝑑ditalic_d-visibility graph, d𝑑ditalic_d-visible points query, or d𝑑ditalic_d-visibility ray shooting (with a Null result if qp¯>dnorm¯𝑞𝑝𝑑\|\overline{qp}\|>d∥ over¯ start_ARG italic_q italic_p end_ARG ∥ > italic_d).

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 𝒪(n)𝒪𝑛\mathcal{O}(n)caligraphic_O ( italic_n ), where n𝑛nitalic_n denotes the number of vertices in the polygon. The first correct 𝒪(n)𝒪𝑛\mathcal{O}(n)caligraphic_O ( italic_n ) solution was proposed by Joe and Simpson [Joe1987].

Subsequently, attention shifted towards polygons with holes until Heffernan and Mitchell [Heffernan1995] introduced the optimal 𝒪(n+hlogh)𝒪𝑛\mathcal{O}(n{\,+\,}h\log h)caligraphic_O ( italic_n + italic_h roman_log italic_h ) algorithm, where hhitalic_h signifies the number of holes, surpassing the previously leading 𝒪(nlogn)𝒪𝑛𝑛\mathcal{O}(n\log n)caligraphic_O ( italic_n roman_log italic_n )-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 𝒪(n3logn)𝒪superscript𝑛3𝑛\mathcal{O}(n^{3}\log n)caligraphic_O ( italic_n start_POSTSUPERSCRIPT 3 end_POSTSUPERSCRIPT roman_log italic_n ) preprocessing time and 𝒪(K+min(h,K)logn)𝒪𝐾𝐾𝑛\mathcal{O}(K{\,+\,}\min(h,K)\log n)caligraphic_O ( italic_K + roman_min ( italic_h , italic_K ) roman_log italic_n ) query time; Inkulu and Kapoor [Inkulu2009] introduced a method with 𝒪(n2logn)𝒪superscript𝑛2𝑛\mathcal{O}(n^{2}\log n)caligraphic_O ( italic_n start_POSTSUPERSCRIPT 2 end_POSTSUPERSCRIPT roman_log italic_n ) preprocessing time and 𝒪(Klog2n)𝒪𝐾superscript2𝑛\mathcal{O}(K\log^{2}n)caligraphic_O ( italic_K roman_log start_POSTSUPERSCRIPT 2 end_POSTSUPERSCRIPT italic_n ) query time; and Chen and Wang [Chen2015] devised an approach with 𝒪(n2logn)𝒪superscript𝑛2𝑛\mathcal{O}(n^{2}\log n)caligraphic_O ( italic_n start_POSTSUPERSCRIPT 2 end_POSTSUPERSCRIPT roman_log italic_n ) preprocessing time and 𝒪(K+log2n+hlog(n/h))𝒪𝐾superscript2𝑛𝑛\mathcal{O}(K{\,+\,}\log^{2}n{\,+\,}h\log(n/h))caligraphic_O ( italic_K + roman_log start_POSTSUPERSCRIPT 2 end_POSTSUPERSCRIPT italic_n + italic_h roman_log ( italic_n / italic_h ) ) 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 𝒪(nh)𝒪𝑛\mathcal{O}(nh)caligraphic_O ( italic_n italic_h ), 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 𝒲𝒲\mathcal{W}caligraphic_W has been triangulated into 𝒯𝒯\mathcal{T}caligraphic_T and that the query point q𝒲𝑞𝒲q{\,\in\,}\mathcal{W}italic_q ∈ caligraphic_W has been located inside a triangle Δ𝒯Δ𝒯\Delta{\,\in\,}\mathcal{T}roman_Δ ∈ caligraphic_T.

Basic Idea and Features

The underlying idea is simple: The TEA computes the visibility polygon 𝒱(q)𝒱𝑞\mathcal{V}(q)caligraphic_V ( italic_q ) by recursively traversing neighboring triangles, starting from ΔΔ\Deltaroman_Δ. 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 𝒲𝒲\mathcal{W}caligraphic_W.

Detailed Operation of the TEA

Starting at ΔΔ\Deltaroman_Δ, a recursive expansion procedure is initiated for each of its edges, gradually forming a set of restricted views around q𝑞qitalic_q.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 q𝑞qitalic_q 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 q𝑞qitalic_q. 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 𝒲𝒲\mathcal{W}caligraphic_W, and the current view from q𝑞qitalic_q 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 𝒱(q)𝒱𝑞\mathcal{V}(q)caligraphic_V ( italic_q ) is the union of all the restricted views formed around q𝑞qitalic_q. 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 q𝑞qitalic_q while adhering to the same order, naturally forming the union of the restricted views.

Vertex Query

When the query point q𝑞qitalic_q 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 ΔΔ\Deltaroman_Δ 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 𝒪(n2)𝒪superscript𝑛2\mathcal{O}(n^{2})caligraphic_O ( italic_n start_POSTSUPERSCRIPT 2 end_POSTSUPERSCRIPT ), where n=|V𝒯|=|V𝒲|𝑛subscript𝑉𝒯subscript𝑉𝒲n{\,=\,}|V_{\mathcal{T}}|{\,=\,}|V_{\mathcal{W}}|italic_n = | italic_V start_POSTSUBSCRIPT caligraphic_T end_POSTSUBSCRIPT | = | italic_V start_POSTSUBSCRIPT caligraphic_W end_POSTSUBSCRIPT |. This is because the recursion may split into two views 𝒪(n)𝒪𝑛\mathcal{O}(n)caligraphic_O ( italic_n ) times, and each view may reach 𝒪(n)𝒪𝑛\mathcal{O}(n)caligraphic_O ( italic_n ) triangles. However, splits into two views that independently reach the same triangle may only occur at the holes of 𝒲𝒲\mathcal{W}caligraphic_W. This implies that the worst-case query time is rather 𝒪(nh)𝒪𝑛\mathcal{O}(nh)caligraphic_O ( italic_n italic_h ).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 𝒪(n)𝒪𝑛\mathcal{O}(n)caligraphic_O ( italic_n ), is incorrect.

Preprocessing

When the input for the TEA is not the triangular mesh 𝒯𝒯\mathcal{T}caligraphic_T, but instead the polygonal environment 𝒲𝒲\mathcal{W}caligraphic_W or the convex polygonal mesh 𝒞𝒞\mathcal{C}caligraphic_C, the TEA query phase must be preceded by the respective preprocessing phase. The preprocessing involves the triangulation of 𝒲𝒲\mathcal{W}caligraphic_W or individual polygons in 𝒞𝒞\mathcal{C}caligraphic_C. For example, this can be achieved by the constrained Delaunay triangulation (CDT), for which exist algorithms running in 𝒪(nlogn)𝒪𝑛𝑛\mathcal{O}(n\log n)caligraphic_O ( italic_n roman_log italic_n ) [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 𝒲𝒲\mathcal{W}caligraphic_W. 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 𝒱V(q)subscript𝒱𝑉𝑞\mathcal{V}_{V}(q)caligraphic_V start_POSTSUBSCRIPT italic_V end_POSTSUBSCRIPT ( italic_q ) visible from the query point q𝑞qitalic_q. Furthermore, there is no need to compute any intersections with the boundary of 𝒲𝒲\mathcal{W}caligraphic_W, which reduces the computational effort. The visible points query follows a similar process, but it requires precomputed point location queries with respect to 𝒯𝒯\mathcal{T}caligraphic_T for the input set of points P𝑃Pitalic_P. 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 P𝑃Pitalic_P 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 q𝑞qitalic_q and the other as the target p𝑝pitalic_p. Similar to other queries, TřiVis initiates the expansion from q𝑞qitalic_q. However, unlike the previously mentioned queries, it does not need to expand in all directions; rather, it expands directly towards p𝑝pitalic_p. This means that only triangles along the line segment qp¯¯𝑞𝑝\overline{qp}over¯ start_ARG italic_q italic_p end_ARG are traversed, which implies that no views are split at holes and the worst-case query time is 𝒪(n)𝒪𝑛\mathcal{O}(n)caligraphic_O ( italic_n ) for this query. If the target is reached before encountering the boundary of 𝒲𝒲\mathcal{W}caligraphic_W, 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 u𝑢uitalic_u guides the expansions. In this case, the expansion procedure terminates as soon as the first intersection with the boundary of 𝒲𝒲\mathcal{W}caligraphic_W is found, and the intersection point is returned.

Computing the visibility graph for a set of query points Q=VP𝑄𝑉𝑃Q=V{\,\cup\,}Pitalic_Q = italic_V ∪ italic_P 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 V𝑉Vitalic_V and each point in P𝑃Pitalic_P, respectively. For the point-point visibility graph, the visible points query is executed for each point in P𝑃Pitalic_P.

TřiVis can also handle d𝑑ditalic_d-visibility queries by incorporating d𝑑ditalic_d 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 d𝑑ditalic_d. This can significantly reduce the number of traversed triangles, especially for small values of d𝑑ditalic_d relative to the expected distance between two points in 𝒲𝒲\mathcal{W}caligraphic_W 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 d𝑑ditalic_d-visibility region, where the output of the expansion procedure, 𝒱dsubscriptsuperscript𝒱𝑑\mathcal{V}^{\prime}_{d}caligraphic_V start_POSTSUPERSCRIPT ′ end_POSTSUPERSCRIPT start_POSTSUBSCRIPT italic_d end_POSTSUBSCRIPT, is a superset of the correct result, 𝒱d𝒱dsubscript𝒱𝑑subscriptsuperscript𝒱𝑑\mathcal{V}_{d}\subset\mathcal{V}^{\prime}_{d}caligraphic_V start_POSTSUBSCRIPT italic_d end_POSTSUBSCRIPT ⊂ caligraphic_V start_POSTSUPERSCRIPT ′ end_POSTSUPERSCRIPT start_POSTSUBSCRIPT italic_d end_POSTSUBSCRIPT, and the final output is obtained by intersecting 𝒱dsubscriptsuperscript𝒱𝑑\mathcal{V}^{\prime}_{d}caligraphic_V start_POSTSUPERSCRIPT ′ end_POSTSUPERSCRIPT start_POSTSUBSCRIPT italic_d end_POSTSUBSCRIPT with a circle centered at the query point with radius d𝑑ditalic_d.

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 ϵitalic-ϵ\epsilonitalic_ϵ-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, ϵitalic-ϵ\epsilonitalic_ϵ-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 𝒲𝒲\mathcal{W}caligraphic_W has been difficult. To address this, we implemented the so-called vertex snapping technique controlled by the ϵ2subscriptitalic-ϵ2\epsilon_{2}italic_ϵ start_POSTSUBSCRIPT 2 end_POSTSUBSCRIPT 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 a𝑎aitalic_a and b𝑏bitalic_b, with c𝑐citalic_c computed as c=(a+b)/ 2𝑐𝑎𝑏2c{\,=\,}(a{\,+\,}b){\,/\,}2italic_c = ( italic_a + italic_b ) / 2 in floating-point representation, the robust geometric predicates indicate that c𝑐citalic_c 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 ϵ1subscriptitalic-ϵ1\epsilon_{1}italic_ϵ start_POSTSUBSCRIPT 1 end_POSTSUBSCRIPT 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.

Algorithm 1 Generic Visibility Query Scheme
1:function X-Query(q𝑞qitalic_q, 1subscript1\mathcal{E}_{1}caligraphic_E start_POSTSUBSCRIPT 1 end_POSTSUBSCRIPT, ϵ2subscriptitalic-ϵ2\epsilon_{2}italic_ϵ start_POSTSUBSCRIPT 2 end_POSTSUBSCRIPT, \dots)
2:     ΔΔabsent\Delta\leftarrow{}roman_Δ ←FindTriangle(q𝑞qitalic_q)
3:     while Δ is NullΔ is Null\Delta\textbf{ is }\text{Null}roman_Δ bold_is roman_Null do
4:         if 1 is Emptysubscript1 is Empty\mathcal{E}_{1}\textbf{ is }\text{Empty}caligraphic_E start_POSTSUBSCRIPT 1 end_POSTSUBSCRIPT bold_is roman_Empty then
5:              return Null         
6:         ϵ1PopSmallest(1)subscriptitalic-ϵ1PopSmallestsubscript1\epsilon_{1}\leftarrow\textsc{PopSmallest}(\mathcal{E}_{1})italic_ϵ start_POSTSUBSCRIPT 1 end_POSTSUBSCRIPT ← PopSmallest ( caligraphic_E start_POSTSUBSCRIPT 1 end_POSTSUBSCRIPT )
7:         ΔΔabsent\Delta\leftarrow{}roman_Δ ←FindTriangleWithEpsilon(q𝑞qitalic_q, ϵ1subscriptitalic-ϵ1\epsilon_{1}italic_ϵ start_POSTSUBSCRIPT 1 end_POSTSUBSCRIPT)     
8:     for vVΔ𝑣subscript𝑉Δv\in V_{\!\Delta}italic_v ∈ italic_V start_POSTSUBSCRIPT roman_Δ end_POSTSUBSCRIPT do
9:         if vq¯ϵ2norm¯𝑣𝑞subscriptitalic-ϵ2\|\overline{vq}\|{\,\leq\,}\epsilon_{2}∥ over¯ start_ARG italic_v italic_q end_ARG ∥ ≤ italic_ϵ start_POSTSUBSCRIPT 2 end_POSTSUBSCRIPT then
10:              return X-ExpandVertex(v𝑣vitalic_v, \dots)              
11:     return X-ExpandTriangle(q𝑞qitalic_q, ΔΔ\Deltaroman_Δ, \dots)

Each visibility query requires the query point q𝑞qitalic_q 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 p𝑝pitalic_p for the two-points visibility query, directional vector u𝑢uitalic_u for the ray-shooting query, and the set of points P𝑃Pitalic_P for the visible points query, or the distance d𝑑ditalic_d for all the d𝑑ditalic_d-visibility queries. The query function also accepts a set of ϵitalic-ϵ\epsilonitalic_ϵ values (a sequence 1subscript1\mathcal{E}_{1}caligraphic_E start_POSTSUBSCRIPT 1 end_POSTSUBSCRIPT and a single ϵ2subscriptitalic-ϵ2\epsilon_{2}italic_ϵ start_POSTSUBSCRIPT 2 end_POSTSUBSCRIPT), which enhance the robustness and control the behavior of the query. The motivation behind these ϵitalic-ϵ\epsilonitalic_ϵ 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 ΔΔ\Deltaroman_Δ containing q𝑞qitalic_q using the robust geometric predicates (line 2). If this fails, it resorts to ϵitalic-ϵ\epsilonitalic_ϵ-geometry, employing the sequence of increasing ϵ1subscriptitalic-ϵ1\epsilon_{1}italic_ϵ start_POSTSUBSCRIPT 1 end_POSTSUBSCRIPT values to locate ΔΔ\Deltaroman_Δ (lines 37). If ΔΔ\Deltaroman_Δ is still not found, it is interpreted that q𝑞qitalic_q lies outside 𝒲𝒲\mathcal{W}caligraphic_W, and the function returns Null (line 5) to indicate this. If ΔΔ\Deltaroman_Δ is found, the function checks whether q𝑞qitalic_q is near any vertices of ΔΔ\Deltaroman_Δ using the ϵ2subscriptitalic-ϵ2\epsilon_{2}italic_ϵ start_POSTSUBSCRIPT 2 end_POSTSUBSCRIPT value (lines 89). If so, the vertex query is executed (line 10), expanding all outer edges of the union of triangles incident to the vertex. When ϵ2>0subscriptitalic-ϵ20\epsilon_{2}>0italic_ϵ start_POSTSUBSCRIPT 2 end_POSTSUBSCRIPT > 0 and qv𝑞𝑣q{\,\neq\,}vitalic_q ≠ italic_v, the operation at lines 810 can be interpreted as vertex snapping, where q𝑞qitalic_q is snapped to v𝑣vitalic_v. Otherwise, the standard expansion procedure is initiated, expanding all edges of ΔΔ\Deltaroman_Δ. 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 ΔΔ\Deltaroman_Δ 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 𝒪(1)𝒪1\mathcal{O}(1)caligraphic_O ( 1 ). This technique preprocesses the triangular mesh 𝒯𝒯\mathcal{T}caligraphic_T by subdividing the bounding box of 𝒲𝒲\mathcal{W}caligraphic_W 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 ΔΔ\Deltaroman_Δ. The test is performed exactly using the robust predicates at line 2 of Alg. 1, and using the ϵ1subscriptitalic-ϵ1\epsilon_{1}italic_ϵ start_POSTSUBSCRIPT 1 end_POSTSUBSCRIPT 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 d𝑑ditalic_d-visibility region from a query point q𝑞qitalic_q. This snippet is simplified for brevity and requires the user to provide the environment data, the query point, and set the visibility range d𝑑ditalic_d (the latter two have default values). The output is a polygonal approximation of the d𝑑ditalic_d-visibility region, with circular arcs sampled using line segments at an angle no greater than π/180𝜋180\pi/180italic_π / 180. 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.

1#include "trivis/trivis.h"
2int main() {
3 using namespace trivis;
4 geom::PolyMap environment; // TODO: Fill the environment.
5 Trivis vis{std::move(environment)}; // Construct the visibility object.
6 geom::FPoint q{0.0, 0.0}; // TODO: Fill the query point q.
7 std::optional<double> d = 10.0; // TODO: Set the visibility range d.
8 // Locate the query point q:
9 std::optional<Trivis::PointLocationResult> pl = vis.LocatePoint(q);
10 if (!pl.has_value()) return EXIT_FAILURE; // q is outside the environment.
11 // Compute the d-visibility region from q:
12 AbstractVisibilityRegion abs = vis.VisibilityRegion(q, pl.value(), d);
13 // Note: abs is an intermediate representation w/o computed intersections.
14 RadialVisibilityRegion reg = vis.ToRadialVisibilityRegion(abs);
15 if (d.has_value()) reg.IntersectWithCircleCenteredAtSeed(d);
16 // Optional post-processing:
17 if (d.has_value()) reg.SampleArcEdges(M_PI / 180.0);
18 geom::FPolygon poly_approx = reg.ToPolygon();
19 // TODO: Do something with the polygonal approx. of the visibility region.
20 return EXIT_SUCCESS;
21} \end{lstlisting}%
22 \end{minipage}%
23 \end{center}%
24 \vspace{-1em}%
25 \caption{Code snippet for computing a $d$-visibility region from a query point $q$ using T\v{r}iVis.}%
26 \label{fig:code_snippet}%
27 \end{figure}
28
29 \section{Performance Evaluation}
30 \label{sec:performance}
31
32 T\v{r}iVis’s performance evaluation focuses on computing visibility polygons in polygonal environments and comparing it with other implementations in terms of runtime behavior and computational time.
33 The evaluation methodology is detailed in Sec.~\ref{subsec:methodology}, and the results are presented in Sec.~\ref{subsec:results}.
34
35 \subsection{Methodology}
36 \label{subsec:methodology}
37
38
39 \paragraph*{Evaluated Implementations}
40
41 Among the other evaluated implementations are the RSA~\cite{Asano1985} and TEA~\cite{Bungiu2014} from the CGAL 2D Visibility package, version 5.6.%
42 \footnote{
43 Available at \url{https://www.cgal.org/}.
44 }
45 These are evaluated with exact predicates and either exact (CE) or inexact (CI) construction kernels.
46 In addition to CGAL, VisiLibity1\footnote{
47 Available at \url{https://karlobermeyer.github.io/VisiLibity1/}.
48 }
49 is included, with its documentation claiming an average $\mathcal{O}(n\log n)$ query performance with no preprocessing; however, the specific algorithm employed in VisiLibity1 is not disclosed in the documentation.
50
51 \paragraph*{Map Dataset}
52
53 Our benchmark environments are derived from a dataset of 35 maps from the Iron Harvest video game, introduced in~\cite{Harabor2022}, and were chosen specifically for their scale and complexity.
54 A notable advantage of this dataset is that it includes three representations of the maps---polygonal, mesh, and grid---while ensuring that the maps maintain the same topology.
55 This provides benefits over robotic datasets, which are either limited to grid representations or, if polygonal, are usually too small and lack the complexity of the Iron Harvest maps.
56 We selected the polygonal representation for our purposes.
57 To ensure each environment is well-formed and connected, we preprocess it by selecting the largest polygon to represent the outer boundary and incorporating all its holes.
58 We discard any additional disconnected artifacts, such as polygons that are not connected to the main polygon with holes or those fully enclosed within the holes.
59 The resulting polygonal environments are characterized by thousands of vertices and dozens to hundreds of holes, typically spanning across 400$\times$400 units.
60 We assessed the validity of the resulting environments using CGAL’s \textsc{CGAL::Arrangement\_2::is\_valid} method, excluding a single invalid instance, \textsc{scene\_sp\_cha\_02}, from the dataset.
61 To illustrate their complexity, Fig.~\ref{fig:iron_harvest} showcases three instances used in the evaluation.
62
63
64 \begin{figure}
65 \centering
66 \subfloat{\includegraphics[height=0.35\columnwidth]{g/scene_sp_pol_03}}
67 \hfill
68 \subfloat{\includegraphics[height=0.35\columnwidth]{g/scene_sp_pol_06}}
69 \hfill
70 \subfloat{\includegraphics[height=0.35\columnwidth]{g/scene_sp_rus_05}}
71 \caption{Examples of polygonal environments from the Iron Harvest dataset.}
72 \label{fig:iron_harvest}
73 \end{figure}
74
75 \paragraph*{Query Points}
76
77 We generated six sets of 1,000 query points for all maps: \textit{In}, \textit{BB}, \textit{Ver}, \textit{NearV}, \textit{Mid}, and \textit{NearM}.
78 The \textit{In} set contains points uniformly distributed inside $\mathcal{W}$, and the \textit{BB} set within its bounding box.
79 The \textit{Ver} set includes randomly selected vertices of $\mathcal{W}$, while the \textit{Mid} set consists of midpoints of edges $\{a, b\} \in \mathcal{T}$, where $\mathcal{T}$ is the CDT of $\mathcal{W}$.
80 The \textit{NearV} and \textit{NearM} sets are based on \textit{Ver} and \textit{Mid} with added normally distributed noise ($\sigma$ randomly selected from $\{10^{-15}, 10^{-14}, \dots, 10^{-1}\}$).
81 For the 34 valid maps, this results in 34,000 points per set, totaling 204,000 query points.
82
83 \paragraph*{Experimental Setup}
84
85 The T\v{r}iVis’s epsilon values are set to $\mathcal{E}_1 {\,=\,} (10^{-18},\allowbreak 10^{-17},\allowbreak \dots,\allowbreak 10^{-9})$ and $\epsilon_2 {\,=\,} 10^{-12}$, and the bucket size for the point location query is set to 1 unit.
86 In VisiLibity1, the same value of $\epsilon_2$ is applied for edge and vertex snapping, as recommended in the documentation.
87 Furthermore, all implementations are single-threaded, compiled in Release mode using GCC 12.3.0, and tested on a personal laptop, the Lenovo Legion 5 Pro 16ITH6H, with an Intel Core i7-11800H (4.60GHz), 16GB of RAM, and running Ubuntu 20.04.6 LTS\@.
88
89 \paragraph*{Runtime Behaviors|Definitions}
90
91 We use CGAL’s TEA with exact predicates and constructions (CGAL-TEA-CE) as the reference implementation $\mathcal{R}$.
92 For the tested implementation $\mathcal{A}$, we define the following exclusive runtime behaviors:
93 \begin{itemize}
94 \item \textit{Crash:} $\mathcal{A}$ crashes due to a segmentation fault, unhandled exception or is killed by the OS\@.
95 \item \textit{Inf:} $\mathcal{A}$ does not finish within its usual time frame likely due to an infinite loop and must be killed manually.
96 \item \textit{NoRef:} $\mathcal{A}$ finishes, but $\mathcal{R}$’s output is unavailable for comparison due to \textit{Crash} or \textit{Inf}.
97 \item \textit{Null:} Both $\mathcal{A}$ and $\mathcal{R}$ return Null.
98 \item \textit{A0R1:} $\mathcal{A}$ returns Null when $\mathcal{R}$ returns a non-Null.
99 \item \textit{A1R0:} $\mathcal{A}$ returns a non-Null when $\mathcal{R}$ returns Null.
100 \item \textit{Same:} $\mathcal{A}$ and $\mathcal{R}$ return the same non-Null output.
101 This is determined by computing the XOR of the two outputs using Clipper2 (recall Sec.~\ref{subsec:dependencies}) and checking if the resulting area is at most $10^{-9}$ times the map area.
102 \item \textit{Weak:} A special case where $\mathcal{A}$ and $\mathcal{R}$ return different non-Null outputs, but the query point is placed precisely on a weakly simple vertex of $\mathcal{W}$.
103 A weakly simple vertex is one with more than one pair of incident edges.
104 For example, two holes touching at a single vertex result in two pairs of incident edges for that vertex.
105 \item \textit{Snap:} A special case where $\mathcal{A}$ and $\mathcal{R}$ return different non-Null outputs, but the query point has been snapped to some vertex of $\mathcal{W}$.
106 \item \textit{Diff:} $\mathcal{A}$ and $\mathcal{R}$ return different non-Null outputs, and none of the special cases \textit{Weak} or \textit{Snap} apply.
107 \end{itemize}
108 To ensure compatibility with the above behaviors, all implementations have been modified to return Null when detecting that the query point lies outside $\mathcal{W}$.
109 Assuming $\mathcal{R}$ is flawless, the most desirable behaviors are \textit{Same} and \textit{Null}, while the least desirable are certainly \textit{Crash} and \textit{Inf}, followed by \textit{Diff} and \textit{A0R1}.
110 The special cases \textit{Weak} and \textit{Snap} are considered acceptable, as they are not necessarily indicative of an error but may hint at a feature-specific behavior.
111 The same applies to \textit{A1R0} when the query point is $\epsilon_1$-close to an edge of $\mathcal{W}$ (as discussed in Sec.~\ref{subsec:robustness}), but in other cases, it is considered undesirable.
112 Although the \textit{NoRef} case should be impossible assuming $\mathcal{R}$ is flawless, as we demonstrate later in this section, it had to be included as CGAL-TEA-CE occasionally encounters \textit{Crash} or \textit{Inf}.
113
114 \subsection{Results}
115 \label{subsec:results}
116
117 \begin{table}
118 \centering
119 \tiny
120 \setlength{\tabcolsep}{2pt}
121 \caption{Runtime Behavior of the Evaluated Implementations}
122 \label{tab:runtime_behavior}
123 \begin{tabularx}{\columnwidth}{ll*{10}{>{\raggedleft\arraybackslash}X}}%
124 \toprule
125 Points & $\mathcal{A}$ (tested imp.) & \textit{\%Crash} & \textit{\%Inf} & \textit{\%NoRef} & \textit{\%Null} & \textit{\%A0R1} & \textit{\%A1R0} & \textit{\%Same} & \textit{\%Weak} & \textit{\%Snap} & \textit{\%Diff} \\
126 \midrule
127 \textit{In} & CGAL-TEA-CE & - & - & - & - & - & - & 100.00 & - & - & - \\
128 & CGAL-TEA-CI & 7.418 & - & - & - & - & - & 92.58 & - & - & - \\
129 & CGAL-RSA-CE & 5.391 & - & - & - & - & - & 94.06 & - & - & 0.55 \\
130 & CGAL-RSA-CI & 11.635 & - & - & - & - & - & 87.92 & - & - & 0.44 \\
131 & VisiLibity1 & - & - & - & - & - & - & 82.86 & - & - & 17.14 \\
132 & T\v{r}iVis & - & - & - & - & - & - & 100.00 & - & - & - \\
133 \midrule
134 \textit{BB} & CGAL-TEA-CE & - & - & - & 42.66 & - & - & 57.34 & - & - & - \\
135 & CGAL-TEA-CI & 4.838 & - & - & 42.66 & - & - & 52.51 & - & - & - \\
136 & CGAL-RSA-CE & 3.456 & - & - & 42.66 & - & - & 53.61 & - & - & 0.28 \\
137 & CGAL-RSA-CI & 7.471 & - & - & 42.66 & - & - & 49.64 & - & - & 0.23 \\
138 & VisiLibity1 & - & - & - & 42.66 & - & - & 47.12 & - & - & 10.22 \\
139 & T\v{r}iVis & - & - & - & 42.66 & - & - & 57.34 & - & - & - \\
140 \midrule
141 \textit{Ver} & CGAL-TEA-CE & 0.012 & 0.018 & - & 0.02 & - & - & 99.95 & - & - & - \\
142 & CGAL-TEA-CI & 4.282 & 0.029 & - & 0.02 & - & - & 95.67 & - & - & - \\
143 & CGAL-RSA-CE & 3.868 & - & 0.026 & 0.02 & - & - & 95.70 & - & - & 0.39 \\
144 & CGAL-RSA-CI & 14.103 & - & 0.024 & 0.02 & - & - & 64.74 & 0.80 & - & 20.31 \\
145 & VisiLibity1 & - & - & 0.029 & - & - & 0.02 & 87.57 & 1.41 & - & 10.97 \\
146 & T\v{r}iVis & - & - & 0.029 & - & - & 0.02 & 98.48 & 1.47 & - & - \\
147 \midrule
148 \textit{NearV} & CGAL-TEA-CE & - & 0.003 & - & 39.45 & - & - & 60.54 & - & - & - \\
149 & CGAL-TEA-CI & 2.821 & 0.003 & - & 39.45 & - & - & 57.72 & - & - & - \\
150 & CGAL-RSA-CE & 2.421 & - & 0.003 & 39.45 & - & - & 57.64 & - & - & 0.49 \\
151 & CGAL-RSA-CI & 5.506 & - & 0.003 & 39.45 & - & - & 52.37 & 0.06 & - & 2.60 \\
152 & VisiLibity1 & - & - & 0.003 & 32.79 & 0.0029 & 6.67 & 50.53 & 0.13 & 3.69 & 6.19 \\
153 & T\v{r}iVis & - & - & 0.003 & 24.44 & - & 15.01 & 58.01 & 0.13 & 2.40 & - \\
154 \midrule
155 \textit{Mid} & CGAL-TEA-CE & - & - & - & 44.81 & - & - & 55.19 & - & - & - \\
156 & CGAL-TEA-CI & 2.971 & - & - & 44.81 & - & - & 52.21 & - & - & - \\
157 & CGAL-RSA-CE & 2.647 & - & - & 44.81 & - & - & 52.15 & - & - & 0.39 \\
158 & CGAL-RSA-CI & 5.194 & - & - & 44.81 & - & - & 49.64 & - & - & 0.35 \\
159 & VisiLibity1 & - & - & - & - & - & 44.81 & 47.47 & - & 0.02 & 7.70 \\
160 & T\v{r}iVis & - & - & - & - & - & 44.81 & 55.19 & - & - & - \\
161 \midrule
162 \textit{NearM} & CGAL-TEA-CE & - & - & - & 25.84 & - & - & 74.16 & - & - & - \\
163 & CGAL-TEA-CI & 3.865 & - & - & 25.84 & - & - & 70.29 & - & - & - \\
164 & CGAL-RSA-CE & 3.268 & - & - & 25.84 & - & - & 70.36 & - & - & 0.53 \\
165 & CGAL-RSA-CI & 6.538 & - & - & 25.84 & - & - & 67.14 & - & - & 0.48 \\
166 & VisiLibity1 & - & - & - & 17.49 & - & 8.35 & 64.54 & - & 0.27 & 9.34 \\
167 & T\v{r}iVis & - & - & - & 13.11 & - & 12.73 & 74.16 & - & - & - \\
168 \midrule
169 Overall & CGAL-TEA-CE & 0.002 & 0.003 & - & 25.46 & - & - & 74.53 & - & - & - \\
170 & CGAL-TEA-CI & 4.366 & 0.005 & - & 25.46 & - & - & 70.16 & - & - & - \\
171 & CGAL-RSA-CE & 3.508 & - & 0.005 & 25.46 & - & - & 70.59 & - & - & 0.44 \\
172 & CGAL-RSA-CI & 8.408 & - & 0.004 & 25.46 & - & - & 61.91 & 0.14 & - & 4.07 \\
173 & VisiLibity1 & - & - & 0.005 & 15.49 & 0.0005 & 9.98 & 63.35 & 0.26 & 0.66 & 10.26 \\
174 & T\v{r}iVis & - & - & 0.005 & 13.37 & - & 12.10 & 73.86 & 0.27 & 0.40 & - \\
175 \bottomrule
176 \end{tabularx}
177 \end{table}
178 \begin{table}
179 \centering
180 \tiny
181 \setlength{\tabcolsep}{1pt}
182 \caption{Computational Time of the Evaluated Implementations}
183 \label{tab:computational_time}
184 \begin{tabularx}{\columnwidth}{lXrcrXrcrXrcrXr}%
185 \toprule
186 $\mathcal{A}$ (tested imp.) & & \multicolumn{3}{r}{Avg.\ init.\ [\textmu{}s]} & & \multicolumn{3}{r}{Avg.\ prep.\ [\textmu{}s]} & & \multicolumn{3}{r}{Avg.\ query [\textmu{}s]} & & PL [\%] \\
187 \midrule
188 CGAL-TEA-CE & & 820,793 & $\pm$ & 657,133 & & 8,129 & $\pm$ & 3,464 & & 142 & $\pm$ & 63 & & 51.1 \\
189 CGAL-TEA-CI & & 618,622 & $\pm$ & 492,005 & & 5,887 & $\pm$ & 2,446 & & 88 & $\pm$ & 42 & & 64.8 \\
190 CGAL-RSA-CE & & 818,563 & $\pm$ & 656,220 & & & - & & & 8,861 & $\pm$ & 3,937 & & 0.8 \\
191 CGAL-RSA-CI & & 619,976 & $\pm$ & 494,630 & & & - & & & 5,243 & $\pm$ & 2,355 & & 1.1 \\
192 VisiLibity1 & & 49 & $\pm$ & 20 & & & - & & & 28,421 & $\pm$ & 12,912 & & 1.2 \\
193 T\v{r}iVis & & 1 & $\pm$ & 1 & & 16,303 & $\pm$ & 7,037 & & 9 & $\pm$ & 6 & & 2.7 \\
194 \bottomrule
195 \end{tabularx}
196 \end{table}
197
198 The runtime behavior of the evaluated implementations, presented as a percentage of the number of query points is shown in Tab.~\ref{tab:runtime_behavior}.
199 For better readability, zero values have been replaced with a dash (-).
200 Recall that CGAL-TEA-CE serves as the reference implementation $\mathcal{R}$; thus, where $\mathcal{R}$ defines the behavior, the CGAL-TEA-CE values represent a form of ‘comparison to itself.’
201
202 First, note that CGAL implementations have a high crash rate, making them largely unusable.
203 The exception is the reference implementation, CGAL-TEA-CE, which crashed only four times and looped seven times out of 204,000 runs.
204 All these issues occurred with the \textit{Ver} or \textit{NearV} sets.
205 In contrast, VisiLibity1 and T\v{r}iVis showed no crashes or infinite loops.
206 Additionally, CGAL implementations, including those with exact constructions (CE), are not mutually consistent in their outputs, as shown by the 0.44\% occurrence of \textit{Diff} for CGAL-RSA-CE\@.
207 Our manual inspections of some of these cases revealed that CGAL-TEA-CE was the one providing correct outputs, making it the most reliable among the CGAL options.
208 VisiLibity1, while not crashing or looping, is inconsistent with the reference in 10.26\% of cases, as indicated by \textit{Diff}, and is therefore unreliable as well.
209
210 Moving our attention to T\v{r}iVis, we see that it is the most reliable, as it never crashed or looped and is consistent with the reference outputs in all cases, except for the \textit{Weak}, \textit{Snap}, and \textit{A1R0} cases, as evidenced by zero occurrences of \textit{Diff} and \textit{A0R1}\@.
211 As previously mentioned, the \textit{Weak}, \textit{Snap}, and \textit{A1R0} cases are not necessarily indicative of an error but may hint at feature-specific behavior.
212 The \textit{Weak} case occurs only for the \textit{Ver} and \textit{NearV} sets and suggests a different strategy used in handling weakly-simple vertex queries in T\v{r}iVis compared to the reference.
213 Upon manual inspection, we found that CGAL-TEA-CE selects only one pair of incident edges as the initial edges for expansion, while T\v{r}iVis considers all of them, making it consistent with our visibility region definition.
214 The \textit{Snap} case occurs only for the \textit{NearV} set and is caused by the vertex snapping technique, as described in Sec.~\ref{subsec:structure}, which helps T\v{r}iVis compute all intersection points correctly and prevent more significant errors.
215 Upon manual inspection, we found that T\v{r}iVis’s outputs for the \textit{Snap} cases align with our expectations and show no indications of more significant errors.
216 The \textit{A1R0} case occurs only for the \textit{Mid} and \textit{NearM} sets.
217 For the \textit{Mid} set, T\v{r}iVis returns non-null outputs in 100\% of cases.
218 This suggests that T\v{r}iVis can compute more visibility polygons in cases where the query point is $\epsilon_1$-close to an edge of $\mathcal{W}$, as discussed in Sec.~\ref{subsec:robustness}, while the reference implementation discards some of these query points as being outside $\mathcal{W}$.
219
220 The computational time of the evaluated implementations is presented in Tab.~\ref{tab:computational_time}.
221 This table shows, for the \textit{In} query set, the average initialization (init.), preprocessing (prep.), and query times, along with the percentage of time (out of the query time) spent on the point location query (PL).
222 Note that init.\ and prep.\ times are averaged over the 34 maps, while the query time is averaged over the 34,000 query points.
223 The init.\ time represents the duration needed to construct the implementation-specific representation of the environment (e.g., \textsc{CGAL::Arrangement\_2} for CGAL) from a simple polygonal representation.
224 The prep.\ time covers the more formal preprocessing operations.
225 While RSA and VisiLibity1 do not require preprocessing, the prep.\ time for the TEA implementations includes the time needed to construct the triangular mesh and bucketing structures for the point location query in T\v{r}iVis.
226 Notably, T\v{r}iVis requires twice as much prep.\ time compared to CGAL-TEA-CE, but the total pre-query time is almost two orders of magnitude lower due to the high init.\ times of the CGAL implementations.
227 Moreover, T\v{r}iVis has the lowest query time among all evaluated implementations.
228 It is one order of magnitude lower than CGAL’s TEA implementations, four orders lower than CGAL’s RSA implementations, and five orders lower than VisiLibity1.
229 It is noteworthy that CGAL’s TEA implementations spend about half of the query time on the point location query, which could potentially be improved with a more efficient point location algorithm.%
230 \footnote{
231 It is important to note that all CGAL visibility polygon implementations assume that the query point is located inside $\mathcal{W}$ and require the user to provide the edge or vertex on which the query point is located, if applicable.
232 This necessitates using the point location implementations from the CGAL 2D Arrangements package prior to performing the visibility query.
233 We use the \textsc{CGAL::Arr\_\allowbreak{}walk\_\allowbreak{}along\_\allowbreak{}line\_\allowbreak{}point\_\allowbreak{}location} implementation, which was the fastest among those available in CGAL that provided correct results without crashing, based on our preliminary experiments.
234 }
235 Even if we halve the average query time of CGAL-TEA-CE, T\v{r}iVis still outperforms it by nearly a factor of eight.
236
237 \section{Concluding Remarks}
238 \label{sec:conclusion}
239
240 This paper presented T\v{r}iVis, a C++ library for computing various visibility-related queries in polygonal environments.
241 We have demonstrated that T\v{r}iVis excels in several aspects compared to similar available implementations:
242 \begin{itemize}
243 \item \emph{Versatility:} T\v{r}iVis offers an extensive set of features, each with a specialized, user-friendly interface.
244 These features include computing visibility polygons, performing two-points and ray-shooting visibility queries, identifying visible points and vertices, constructing visibility graphs, and executing rapid point location queries.
245 It also provides various utility functions for managing polygonal environments and query outputs.
246 Additionally, T\v{r}iVis supports efficient computations of all queries with an optional limited range constraint.
247 \item \emph{Reliability:} T\v{r}iVis is characterized by its reliable and predictable behavior.
248 It avoids crashing or infinite looping and consistently produces outputs that align with user expectations, as confirmed by our evaluation on highly complex query instances.
249 \item \emph{Performance:} With an average query time of 9\,\textpm\,6\,\textmu{}s, T\v{r}iVis outperforms all other implementations by at least an order of magnitude, while maintaining preprocessing times below 20\,ms for the benchmark instances.
250 \end{itemize}
251 Moreover, the core functionality is independent of external libraries.
252 T\v{r}iVis is freely available for private, research, and institutional use at \url{https://github.com/janmikulacz/trivis}.
253
254 \bibliographystyle{IEEEtran}
255 \bibliography{main}
256 \pagebreak
257
258\end{document}’