Boolean operation on polygons is one of the oldest and best-known problems, and it has attracted much attentions, due to its simple formulation and broad applications in various disciplines such as computational geometry, computer graphics, CAD, GIS, motion planning [MarkdeBerg:computational, JamesDFoley:computer, YvonGardan:anAlgorithm, JohnEHopcroft:robust, Francisco:aNew, KevinWeiler:HiddenSurface]. When the polygons to be operated are conic polygons (whose boundaries consist of conic segments or second degree curves), researchers have made corresponding efforts, see, e.g., [EricBerberich:aComputational, Yong-XiGong:Boolean, www:cgal, www:lead]. The conic polygon has several special or degenerate cases: (i) the linear polygon (known as traditional polygon), whose boundaries consist of only linear curves, i.e., straight line segments; and (ii) the circular-arc polygon, whose boundaries consist of circular-arcs and/or straight line segments. The natural problem — boolean operation on traditional polygons — has been well investigated, see e.g., [BalaRVatti:aGeneric, AriRappoport:AnEfficient, GuntherGreiner:efficient, AvrahamMargalit:Analgorithm, YongKuiLiu:AnAlgorithm, MRivero:Boo, YuPeng:aNew, Francisco:aNew, DKrishnan:systolic, RDAndreev:Algorithm, You-DongLiang:AnAnalysis, Patrick-GillesMaillot:aNew]. Surprisingly, in existing literature, (almost) no article focuses on another natural problem — boolean operation on circular-arc polygons. In fact, boolean operation on circular-arc polygons can also find many applications. For instance, deploying sensors to ensure wireless coverage is an important problem [bangWang:coverage, SeapahnMeguerdichian:coverage]. The sensing range of a single sensor is a circle. With obstacles, its sensing range is cut off, shaping a circular-arc polygon. When we verify the wireless coverage range of sensors, boolean operation on circular-arc polygons is needed. As another example, assume there are a group of free-rotating cameras used to monitor a supermarket. The visual range of a single camera can be regarded as a circle, as it is to be freely rotated. Various obstacles such as goods shelves usually impede the visions of cameras, here boolean operation can be used to check the blind angles. Last but not least, consider a group of free-moving robots used to guide the visitors in a museum. Since the energy of a single robot is limited, its movable region is restricted to a circle. With the impact of various obstacles such as exhibits, the original movable region is to be cut off by these obstacles. When we verify if every place in the museum can be served by at least a robot, boolean operation on circular-arc polygons is also needed.
Although the solution used to handle conic polygons can also work for its special cases, the special cases however, usually have their unique properties; directly appealing to the algorithm used to handle conic polygons is usually not efficient enough. It is just like when the applications only involve traditional polygons, we usually incline to use the solutions targeted for traditional polygons rather than the ones for conic polygons. With the similar argument, when the applications only involve circular-arc polygons, a targeted solution for circular-arc polygons should be favourable for potential users.
Motivated by these, this paper makes the effort to the problem of boolean operation on circular-arc polygons. First of all, a concise and easy-to-operate data structure called APDLL is naturally developed. Based on this concise structure, we propose an algorithm named RE2L that consists of three main steps. The first step is the kernel of RE2L, yielding two special sequence lists. Specifically, the kernel integrates three surprisingly simple yet efficient strategies: (i) it introduces the concept of related edges, which is used to avoid irrelevant computation as much as possible; (ii) it employs two special sequence lists, each one is a compound structure with three domains; they are used to let the decomposed arcs, intersections and processed related edges be well organized, and thus immensely simplify the subsequent computation; and (iii) it assigns two labels to each processed related edge before the edge is placed into the red-black tree; this contributes to avoiding the “false” intersections being reported, and speeding up the process of inserting the reported intersections into their corresponding edges. The second step of our algorithm produces two new linked lists in which the intersections, appendix points, and original vertexes have been arranged, and the decomposed arcs have been merged. To obtain these two new linked lists, two important but easy-to-ignore issues, “inserting new appendix points” and “merging the decomposed arcs”, are addressed. The third step is to obtain the resultant polygon by traversing these two new linked lists. In order to correctly traverse them, the entry-exit properties are naturally adopted, and three traversing rules are developed. Given two circular-arc polygons with and edges, respectively, we prove that the proposed algorithm runs in time, using space. To sum up, we make the following main contributions.
We highlight the circular-arc polygon is one of special cases of the conic polygon, and boolean operation of circular-arc polygons has also many applications.
We devise a concise and easy-to-operate data structure, and develop a targeted algorithm for boolean operation on circular-arc polygons.
We analyse the complexity of our proposed algorithm, and conduct extensive experiments to demonstrate its efficiency and effectiveness.
While this paper focuses on boolean operation of circular-arc polygons, we show our techniques can be easily extended to compute boolean operation of other types of polygons.
The remainder of the paper is organized as follows. Section 2 reviews previous works most related to ours, and Section 3 introduces the preliminaries, including some basic concepts, the data structure employed by our algorithm, and the top-level framework of our algorithm. Section 4 presents the central ideas of our algorithm. The details of constructing two new linked lists and traversing them are addressed in Section 5 and 6, respectively. Section 7 analyses the time/space complexity of our algorithm. Section 8 evaluates our algorithm based on extensive experiments. Section 9 shows our techniques can be easily extended to compute boolean operation of other types of polygons, and finally Section 10 concludes this paper.
2 Related work
We first clarify several technical terms for ease of presentation. It is well known that there are three typical boolean operations: intersection, union, and difference. Note that polygon clipping mentioned in many papers actually is to compute the difference of two polygons [BalaRVatti:aGeneric]. Given two polygons, the one to be clipped is called the subject polygon, another is usually called the clip polygon or clip window [Sutherland:reentrant, BalaRVatti:aGeneric, You-DongLiang:AnAnalysis]. Given a polygon, if there is a pair of non-adjacent edges intersecting with each other, this polygon is usually called the self-intersection polygon [RDAndreev:Algorithm, GuntherGreiner:efficient, MRivero:Boo]. Throughout this paper, the traditional polygon refers to the polygon whose boundaries consist of only straight line segments, regardless of whether it is convex or concave. We are now ready to review the previous works most related to ours.
2.1 Boolean operation on traditional polygons
In existing literature, there are many papers studying boolean operation of traditional polygons. For example, Sutherland-Hodgeman [Sutherland:reentrant] proposed an elegant algorithm dealing with the case when the clip polygon is convex. Liang et al. [You-DongLiang:AnAnalysis] gave elaborate analysis on the case when the clip polygon is rectangular. Andreev [RDAndreev:Algorithm] and Greiner-Hormann [GuntherGreiner:efficient] proposed general algorithms that can handle concave polygons with holes and self-intersections. Later, Liu et al. [YongKuiLiu:AnAlgorithm] further optimized Greiner-Hormann’s algorithm. Rivero-Feito [MRivero:Boo] achieved boolean operation of polygons based on the concept of simplicial chains. Peng et al. [YuPeng:aNew] also adopted simplicial chains, and improved Rivero-Feito’s algorithm. Recently, Martinez et al. [Francisco:aNew] proposed to subdivide the edges at the intersection. These works lay a solid foundation for the future research. Compared to these works, this paper focuses on boolean operation of circular-arc polygons, and thus is different form theirs.
2.2 Boolean operation on conic/general polygons
Researchers have also made corresponding efforts on boolean operation of conic polygons. For example, Berberich et al. [EricBerberich:aComputational] proposed to use the plane sweep method to achieve boolean operation of conic polygons. Gong et al. [Yong-XiGong:Boolean] achieved boolean operation of conic polygons using the topological relation between two conic polygons, this method does not require x-monotone conic arc segments. Both of algorithms can support boolean operation of circular-arc polygons, as the conic polygon is the general case of the circular-arc polygon. Note that the computational geometry algorithms library (CGAL) [www:cgal] can also support boolean operation of circular-arc polygons. Inspecting the source codes of CGAL, we realize that its idea is directly appealing to the algorithm of boolean operation on general polygons, defined as GeneralPolygon_2 in CGAL. To some extent the general polygon can be looked as the most general case, as its edges can be line segments, circular arcs, conic curves, cubic curves, or even more complicated curves. The essence of the algorithm in CGAL is also to use the plane sweep method, and is also to use the DCEL structure to represent the (general) polygons, which are similar to that in [EricBerberich:aComputational]. These excellent works give us a lot of inspiration, our work yet is different from theirs, as this paper focuses on one of special cases of conic polygon; particularly, we give insights into its unique properties, employ a concise data structure customized for this special case, and develop the targeted algorithm.
3.1 Basic concepts
(Circular-arc polygon) A polygon is a circular-arc polygon such that its boundaries consist of circular arcs, or both straight line segments and circular arcs.
(Non-x-monotone circular arc) Given any circular arc, it is a non-x-monotone circular arc such that there is at least one vertical line that intersects with the circular arc at two points.
(X-monotone circular arc) A circular arc is an x-monotone circular arc such that there is at most one intersection with any vertical line.
Note that in the paper we slightly abuse the term intersection but its meaning should be clear from the context.
(Decompose non-x-monotone circular arc) Let be an arbitrary non-x-monotone circular arc, and be its corresponding circle. Assume that is a horizontal line passing through the center of . We have that can decompose into at least two and at most three x-monotone arcs.
Since passes through the center of , it must intersect with at two points, say and . For any non-x-monotone circular arc , it has only two cases. (i) both and are located on ; and (ii) only (or ) is located on . For case 1, based on analytic geometry, it is easy to know that will be decomposed into two arcs by when (or ) is the endpoint of (see Figure 1(a)); otherwise, will be decomposed into three arcs by (see Figure 1(b)). For case 2, we can also easily know that will be decomposed into two arcs by (see Figure 1(c)). In addition, both the upper semi-circle and below semi-circle of are x-monotone arcs; and any sub-arc of upper or below semi-circle is also an x-monotone arc. Pulling all together, hence the theorem holds. ∎
It is well known that the traditional polygon can be represented by a series of vertexes. This method however is invalid for polygons containing circular arcs, as two vertexes cannot exactly determine a circular arc segment (note: it may be a major or minor arc). Even so, this ambiguity can be easily eliminated by adding an appendix point. For clarity, a traditional vertex is denoted by , and an appendix point is denoted by . For example, determine a circular-arc polygon with four edges (including one circular arc segment and three straight line segments , , ). Unless stated otherwise, in the rest of the paper we always use and to denote the line segment and the arc segment, respectively. In order to efficiently operate circular-arc polygons, we devise a data structure called APDLL (appendix point based double linked list). Specifically, each node in the double linked list consists of several domains below.
Data: , the coordinates of a point.
Tag: Boolean type, it indicates whether this point is a traditional vertex or an appendix point.
Crossing: Boolean type, it indicates whether this point is an intersection.
EE: Boolean type, it indicates what property (entry or exit) an intersection has.
PPointer: Node pointer, it points to the previous node.
NPointer: Node pointer, it points to the next node.
We remark that the entry-exit property of the intersection is used to traverse, more details about the entry-exit property will be discussed in Section 6. For ease of understanding our proposed method, we next describe the overall framework of our algorithm, and then go into the details.
3.3 Top-level of our algorithm
Let and respectively denote two circular-arc polygons to be operated, and let denote the resultant polygon (i.e., the output of our algorithm). The overall framework of our proposed method is described as follows.
Algorithm 1 RE2L
The function ConstructSequenceLists() is used to construct two sequence lists in which the intersections are well organized, and the decomposed arcs are well arranged. Note that this function is the kernel of our algorithm. The function ConstructNewLinkedLists() is used to construct two new linked lists in which the intersections, appendix points, and original vertexes have been arranged, and the decomposed arcs have been merged. The function TraverseLinkedLists() is used to obtain the resultant polygon by traversing the two new linked lists.
4 The kernel of RE2L
4.1 Related edges
One of our strategies is to choose related edges before doing others. The purpose of choosing related edges is to avoid operations that are irrelevant with obtaining the final result as much as possible. We next show how to obtain the related edges, and inspect their properties.
(Extended boundary lines) Given a circular-arc polygon, we can always find its minimum bounding rectangle (MBR). Without loss of generality, assume the coordinates of left-bottom corner of the MBR are (,), the one of right-top corner of the MBR is (,). Then, the following four lines, X=, X=, Y=, Y= are respectively the left, right, bottom and top extended boundary lines of this circular-arc polygon.
(Effective axis) Given two circular-arc polygons and , let be the intersection set of their MBRs. If the horizontal span of is larger or equal to its vertical span; then, the y-axis is the effective axis. Otherwise, the x-axis is the effective axis.
(Related edges) Given two circular-arc polygons and , we use /, /, / and / to denote the left, right, top and bottom extended boundary lines of /, respectively. Without loss of generality, assume the effective axis is the x-axis and , where denotes is in the left of . Then, the following edges are related edges. (i) edges located between and ; or (2) edges intersected with or .
See Figure 2(a) for example, edges and are related edges as they intersect with . Similarly, edges and are also related edges.
In Definition 6, there are actually other cases, e.g., “” or the effective axis is the y-axis; these cases are similar to the listed case, omitted for saving space.
(Processed related edges) Given a number of related edges, we decompose them if there are non-x-monotone arcs, we call all the edges (after decomposing) the processed related edges.
Given related edges, if there is no non-x-monotone arc among them, the number of processed related edges is . Otherwise, the number of processed related edges is larger than and no more than .
It is immediate by Theorem 1. ∎
Up to now, we have discussed the properties of related edges, and explained how to choose related edges from two circular-arc polygons. We next show how to use two sequence lists to manage the processed related edges as well as other important components.
4.2 Two sequence lists
The main purpose of the two sequence lists is to let the processed related edges, intersections and decomposed arcs be well organized, which can facilitate the subsequent operations. Specifically, each item in the two sequence lists is a compound structure consisting of three domains: (i) the processed related edge; (ii) the intersections (if exist) on this edge; and (iii) a tri-value switch. For ease of discussion, we denote by and the two sequence lists, by the th item in (), and by , and the three domains of , respectively.
The processed related edges in each sequence list are stored along the direction of counter-clockwise w.r.t. the original circular-arc polygon. For example, regarding to circular-arc polygons in Figure 2, we construct two sequence lists as shown in Figure 3. Note that when there are multiple intersections on an edge, we should let these intersections in order. See of Figure 3 for example, the point is in the front of the point . Regarding to the third domain , it is assigned to either 0, 1, or 2. The assignment rules are as follows. When the edge is not a decomposed arc, we assign “0” to . In this example, for any (where denotes the cardinality of ), is set to 0, as there is no decomposed arc. Otherwise, we assign “1” or “2” to . The readers may be curious why we use two different values. The purpose is to differentiate the decomposed arcs which are from different non-x-monotone arcs. This can help us efficiently merge them in the future. (The details on how to merge them will be discussed in Section 5.) Given a series of decomposed arcs, we assign “1” to each decomposed arc that is from the 1st (3rd, 5th, ) non-x-monotone arc, and assign “2” to each decomposed arc that is from the 2nd (4th, 6th, ) non-x-monotone arc.
See Figure 4(a) for example, there are five related edges in . Furthermore, Figure 4(b) illustrates eight processed related edges (after we decompose them based on Theorem 1), implying that . Based on the assignment rules, the values of the third domains should be “0, 1, 1, 2, 2, 1, 1, 0”, respectively.
Thus far, we have shown how to use two sequence lists to manage the processed related edges and intersections. Note that, in order to obtain the intersections, a standard method is the plane sweep method algorithm [JonLouisBentley:Algorithms, MichaelIanShamos:Geometric]. In this paper, we do not directly use this algorithm. Instead, we add two labels to avoid the “false” intersections being reported, and to speed up the process of inserting the reported intersections into their corresponding edges. (Remark: here the false intersections refer to the vertexes of polygons.) We next give a brief review of the plane sweep algorithm, and then show more details about the two labels.
Plane sweep method. Let be a heap, be a red black tree, and be a vertical sweep line. The basic idea of the plane sweep method is as follows. First, it sorts the endpoints of all segments according to their x-coordinates, and then puts them into . Next, it sweeps the plane (from left to right) using . At each endpoint during this sweep, if an endpoint is the left endpoint of a segment, it inserts this segment into ; in contrast, if it is the right endpoint of a segment, it deletes this segment from . Note that all the segments intersecting with are stored (in order from bottom to top) in . In particular, when moves from one endpoint to another endpoint, it always checks whether or not newly adjacent segments intersect with each other; If so, it computes the intersection. In this way, all intersections can be obtained finally.
4.3 Two labels
We can easily see that the plane sweep method directly inserts a segment into the red-black tree , if the point () is the left endpoint of the segment. Instead, we assign two labels to the segment before it is inserted into . Note that the segment discussed here refers to the processed related edge. For clearness, we denote by and the two labels, respectively.
is the boolean type, identifying that a segment is from which one of the two circular-arc polygons. Specifically, if the segment is from , we assign true to ; otherwise, we assign false to . Recall that the plane sweep method always checks whether or not two segments intersect with each other, when they are adjacent. Our proposed method do not need to check them regardless of whether or not they intersect, if the first labels of two adjacent edges have the same value. This can avoid the unnecessary test and the “false” intersections.
is an integer type denoting a serial number, which corresponds to the “id” of an item stored in the sequence list (note: the “id” information of each item is implied, as we adopt the sequence list to store the items). When we detected an intersection, this label can help us quickly find the item in the sequence list, and then insert the intersection into this item. See Figure 2(b) for example, and of edge are assigned to true and 1, respectively. When we detected the intersection , we thus can quickly know that we should insert the intersection into (i.e., the first item of ). Otherwise, we have to scan the sequence list in order to insert the intersection into an appropriate item, this way is inefficient especially when (or ) is large.
4.4 The algorithm
Let and be the related edges from and , respectively. Given a segment , we use and to denote the two labels of segment . Algorithm 2 below illustrates the pseudo-codes of constructing the two sequence lists.
Algorithm 2 ConstructSequenceLists
Output: and , and
(1)Find the MBRs, effective axis and extended boundary lines
(2) related edges from // where
(3)Create two empty sequence lists and
(5)InitializeSequenceList () // cf. Algorithm 3
(6)Sort the endpoints of the segments (from ), and
put them into
(7) // is a red-black tree
(8)for each point
(9)Let be the segment containing the point , and be
the segment immediately above or below
(10)if ( is the left endpoint of segment )
(11)Assign two “labels” to , and insert into
(12)if ( )
(13)if ( intersects with )
(14)Insert the intersection into , and also insert it
into and , respectively
(15)else if ( is the right endpoint of segment )
(17)if ( intersects with and this intersection )
(18)Insert this intersection into , and also insert it
into and , respectively; delete from
(19)else // is an intersection of two segments, say and
(20)Swap the position of and // assume is above
(20)Let be the segment above , and be
the segment below
(21)if ( or )
(22)if ( intersects with , or intersects with )
(23)Insert the intersection point into , and also insert
it into and , respectively
(24)return and , and
We first choose the related edges based on the extended boundary lines (Lines 1-2). Next, we construct two empty sequence lists and initialize them (Lines 3-5). After this, we compute the intersections (Lines 6-23). In particular, when we compute the intersections, two labels are assigned to the segment before it is inserted into the red-black tree (Line 11), and we use the two sequence lists to store the intersections (Lines 14, 18 and 23). Note that, the pseudo-codes of initializing the two sequence lists are depicted in Algorithm 3. This algorithm decomposes non-x-monotone arcs, puts the processed related edges into the sequence lists in an orderly manner, and assigns appropriate values to the tri-value switches.
Algorithm 3 InitializeSequenceList
(1) // the is used to set the tri-value switch
(2)for each related edge
(3)if ( is a non-x-monotone circular arc )
(4)Decompose it and put the decomposed arcs into ,
and set the value of each tri-value switch to “”
(7)else // =2
(9)else // is not a non-x-monotone circular arc
(10)Put it into , set the value of tri-value switch to “0”
Given two circular-arc polygons with and edges, respectively, and assume there are related edges between the two polygons, we have that constructing the two sequence lists can be finished in time, where is the number of intersections.
To obtain the related edges, we first need to find the MBRs of two polygons, which takes linear time. We next determine the effective axis by comparing the horizontal and vertical spans of the intersection set of two MBRs, which can be finished in constant time. Furthermore, the extended boundary lines can be obtained in constant time once we obtain the effective axis. Based on two extended boundary lines, we finally obtain the related edges by comparing the geometrical relationship between each edge and extended boundary lines, which also takes linear time. Thus, Lines 1-2 take time.
Creating two empty sequence lists takes constant time. In addition, in order to initialize the two sequence lists, we need to decompose each non-x-monotone arc. Decomposing a single arc can be finished in constant time. In the worst case, all the related edges are non-x-monotone arcs. Even so, there are no more than items in the two sequence lists, according to Theorem 1. So, initializing two sequence lists takes time. Sorting all the endpoints of segments in the heap takes time, and initializing the red-black tree takes constant time. Thus, Lines 3-7 take time.
As there are no more than segments in and , the number of endpoints thus is no more than . So we can easily know that the number of executions of the for loop (Line 8) is no more than . Within the for loop, each operation (e.g., insert, delete, swap, find the above/below segment) on can be finished in time, as the number of segments in never exceeds . Additionally, each of other operations (e.g., assign labels to the segment, determine if two segments intersects with each other) can be finished in constant time. Thus, Lines 8-23 takes time, i.e., time. At last returning the results takes constant time (Line 24). Pulling all together, hence the theorem holds. ∎
We have shown how to construct two sequence lists used to manage the processed related edges and intersections. Based on the two sequence lists, we next explain how to construct two new linked lists used to obtain the resultant polygon.
Recall Section 3.2, the input polygons and are also stored using linked lists. Unless stated otherwise, the terms “input polygons” and “original linked lists” are used interchangeably in the rest of the paper.
5 Two new linked lists
It is pretty simple to construct two new linked lists, based on the two sequence lists obtained in the previous step. By the large, we use the information stored in two sequence lists to replace those related edges in original linked lists. Note that there are two important yet easy-to-ignore issues needed to be handled when we construct new linked lists. We next check more details about these issues, and then present the algorithm of constructing new linked lists.
5.1 New appendix points
Recall Section 3.2, we always add an appendix point between two vertexes if an edge is a circular arc. When we replace related edges with the information stored in sequence lists, we also have to ensure this property. It is easy to know that, when the intersections appear on a circular arc, this arc will be decomposed by these intersections. We thus have to add the new appendix point for each sub-segment, in order to eliminate the ambiguity.
Suppose there are intersections on a circular arc; then, we need to insert at least and at most new appendix points.
Since intersections can subdivide a complete circular arc into small circular arcs, and for each small circular arc one appendix point is needed and enough to eliminate the ambiguity. Clearly, appendix points are needed for small circular arcs. Furthermore, there is an appendix point beforehand. Therefore, when there is no intersection coinciding with this appendix point, only new appendix points are needed. Otherwise, we need new appendix points. ∎
Besides the above issue, another issue is to handle the decomposed arcs. We decomposed non-x-monotone arcs into x-monotone arcs ever, we thus need to merge them. The natural solution is to compare each pair of adjacent edges of the resultant polygon, checking if they can be merged into a single arc. This way however is inefficient because (i) most of edges of the resultant polygon may not need to be merged; and (ii) given two adjacent arcs, let and respectively denote their corresponding circles; checking if the two arcs can be merged into a single arc needs to compute the centres of and , this will use trigonometric functions (which could have been avoided). We next show how to efficiently merge them, in the aid of the sequence lists.
5.2 Decomposed arcs
We merge the decomposed arcs when constructing new linked lists, rather than merge them after obtaining the resultant polygon. In particular, we here utilize the information stored in the tri-value switch to improve the efficiency. Specifically, given an item , if (or 2), we continue to fetch its next item from the sequence list if . In this way, a group of consecutive items are fetched from the sequence list. Without loss of generality, assume that we have fetched consecutive items, , , . Then, we do as follows.
If , we discard the fetched items instead of merging them. This is because there is no intersection on these decomposed arcs, the merged result should be the same as the edge in the original linked list.
Otherwise, we insert new appendix points, merge decomposed arcs, and replace the edge in the original linked list.
Let us revisit Figure 4(b); recall that there are eight items in , and the values in their tri-value switches are “0, 1, 1, 2, 2, 1, 1, 0”, respectively. Although , we discard the two items instead of merging them, as . Similarly, we also discard the items and . Note that, for the 6th and 7th items, and ; thus, we insert a new appendix point, merge the two decomposed arcs, and use the merged result to replace the edge in the original linked list.
Note that, the consecutive items mentioned earlier are actually the decomposed arcs generated from a single non-x-monotone circular arc. According to Theorem 1, we can easily build the following theorem.
Let be the number of consecutive items, we have that and .
5.3 The algorithm
Let and be the two new linked lists, respectively. Algorithm 4 below depicts the pseudo-codes of constructing two new linked lists. For each edge in the original linked list, we check whether it is a related edge. If so, we further check whether is a decomposed arc. Lines 7-13 are used to deal with the case when it is not a decomposed arc. In contrast, Lines 14-22 are used to handle the opposite case. In this case, we first fetch all the consecutive decomposed arcs (Lines 15-18), and then check if there are intersections on these decomposed arcs. If it is not, we put the edge into (Lines 19-20). Otherwise, we insert new appendix points, merge decomposed arcs, and put the merged result (instead of ) into (Lines 21-22).
Algorithm 4 ConstructNewLinkedLists
Input: and , and , and
(1)Set , and
(3)for each edge
(4)if ( )
(6)else // is a related edge
(7)if () // not a decomposed arc
(8)if () // no intersection
(9), and add to
(11)if ( is a circular arc)
(12)Insert new appendix points
(13)Put the information from into , and
(14)else // (or 2)
(15)Set , and
(16)do // copy the consecutive decomposed arcs
(22)Insert new appendix points, merge decomposed
arcs, and put the merged result into
Suppose we have obtained the two sequence lists and ; then, constructing the two new linked lists and takes time.
Inserting a single appendix point takes constant time. In the worst case, all the intersections are located on arcs rather than on line segments. Even so, there are no more than new appendix points according to Theorem 3. Thus inserting appendix points takes time. Merging consecutive decomposed arcs takes constant time, as . In the worst case, all the related edges are non-x-monotone arcs, hence merging all consecutive decomposed arcs takes time.
Since the number of edges in and is , the number of executions of the second for loop (Line 3) is . Specifically, the number of executions of Line 4 is , and the one of Line 6 is . Even if all related edges are non-x-monotone arcs, the number of executions of Line 17 is no more than . Furthermore, within the for loop, each operation takes constant time (note: here we no longer consider the time for inserting new appendix points and merging decomposed arcs, as we have analysed them in the previous paragraph). Therefore, Lines 4-5 and Lines 7-22 take and time, respectively. Pulling all together, this completes the proof. ∎
To this step, we have obtained and . We next show how to traverse them in order to obtain the resultant polygon.
In order to correctly traverse the two linked lists, we need to assign the entry-exit properties to intersections.
6.1 Entry-exit property
The entry-exit property is an important symbol that was ever used in many papers focusing on boolean operation of traditional polygons (see e.g., [GuntherGreiner:efficient, YongKuiLiu:AnAlgorithm]). This technique can be equivalently used to the case of our concern. It is quite straightforward to assign the intersections with such properties. Specifically, we assign the intersections with the entry or exit property alternately.
See Figure 5 for example. and are two input polygons. We can easily obtain the two new linked lists and using algorithms discussed before. Here , and . Regarding to , we assign “entry, exit, entry, exit” to “”, respectively. The entry-exit properties of “” in are the same as the ones in . See Figure 6(a).
Once the entry-exit properties are assigned to intersections, we then obtain the resultant polygon based on the traversing rules below.
6.2 Traversing rules
Let be an intersection point of such that has the entry property. Let be a vertex of such that does not locate in . There are three typical boolean operations: intersection, union and difference. We next discuss their traversing rules, respectively. Note that in the rest of discussion, the default traversing direction is counter-clockwise, unless stated otherwise.
We start to traverse using as the starting point. Once we meet an intersection point with the exit property, we shift to , and traverse it. Similarly, if we meet an intersection point with the entry property in , we shift back to . In this way, a circuit will be produced. After this, we check if there is another intersection point of such that (i) it has the entry property; and (ii) it is not a vertex of the produced circuit. If no such an intersection point, we terminate the traversal, and this circuit is the intersection between and . Otherwise, we let this intersection point as a new starting point, and traverse the two new linked lists (using the same method discussed just now), until no such an intersection point exists. In the end, we get multiple circuits, which are the intersection between and . See Figure 6(b) for example, we first choose in as the starting point, and then traverse the two linked lists, getting a circuit (see the dashed lines). Moreover, there is no other intersection point satisfying the two conditions mentioned before. Therefore, the intersection is .
We start to traverse using as the starting point. Once we meet an intersection point with the entry property, we shift to , and traverse it. Similarly, if we meet an intersection point with the exit property in , we shift back to . In this way, a circuit will be produced, which is the union between and . See Figure 6(c) for example, we first choose as the starting point, and then traverse the two linked lists, until we are back to the starting point . Therefore, is the union between and .
We start to traverse using as the starting point. Once we meet an intersection point with the entry property, we shift to , but traverse along the direction of clockwise. Similarly, if we meet an intersection point with the exit property in , we shift back to . In this way, a circuit will be produced. Furthermore, we check if there is another vertex of such that (i) it is not a vertex of any produced circuit; and (ii) it does not locate in . If no such a vertex, we terminate the traversal, and this circuit is the difference between and . Otherwise, we let the vertex as a new starting point, and traverse the two new linked lists (using the same method discussed just now), until no such a vertex exists. In the end, we get multiple circuits, which are the difference between and . See Figure 6(d) for example, we first choose as the starting point, and begin to traverse. Since has the entry property, we shift to (note: we traverse along the direction of clockwise, the next node of thus is ). Since has the exit property, we shift back to . In this way, we get a circuit (see the black dashed lines). After this, we choose as a new starting point since it satisfies the two conditions mentioned above, and then continue to traverse, getting another circuit (see the grey dashed lines). Thus, the difference between and consists of two parts, i.e., and .
6.3 The algorithm
In some cases the result consists of multiple circuits, we denote by the linked list used to store the th circuit. Let be a node of where , we denote by the current node when we traverse , and denote by the next node of . Furthermore, we denote by the intersection point of such that has the entry property and it is not an vertex of any produced circuit, and we use to denote there exists such a point. Algorithm 5 below illustrates the pseudo-codes used to obtain the intersection result. (Remark: the pseudo-codes of other two operations can be easily constructed based on the traversing rules, and are the similar as this algorithm, we here omit them for saving space.)
Algorithm 5 TraverseLinkedLists
(3)Assign entry-exit property to
(6)Choose a starting point from
(8)Let // i.e., let be a new starting point
(9)Set , and
(12)if ( is not an intersection point)
(13)Let , and put into
(15)Shift to , choose the node such that
, let , and put into