6.2 Halfplane query
6.2.2 Preprocessing and query algorithms
In this section, we first propose a sub-optimal incremental algorithm that is able to construct the wedge subdivision in O(n log2n) time. (In Section 6.2.3 we improve this to O(n log n).) We use an augmented balanced search tree, D, as the underlying data structure to maintain the upper envelope of oi after we insert each wedge wi into the
dual space. (The upper-envelope is x-monotone.) Recall that oi is the outer face ofPi.
Here, each node in D represents a segment (or an infinite ray) on oi. Specifically, we
store in each node, p, the following fields:
1) u and v, indicating the line y = ux + v that goes through the segment represented by p;
2) x1 and x2, where x1 < x2, indicating the range of the segment in the x-dimension;
3) w, the wedge corresponding to the segment represented by p.
It is clear that any vertical line will intersect the upper envelope exactly once, which naturally gives us a total order among all the segments on it. Therefore, any arbitrary number between x1 and x2 suffices to act as the key for comparison. WithD in hand,
we can efficiently tell, in O(log n) time, whether a point in the dual space is above or below the envelope. In addition, we define the following convenient helper functions,
which will be used repeatedly as black boxes.
1) remove(low , high): This method cuts off the portion of the upper envelope whose x-coordinate is in the range (low , high). This function will remove several existing seg- ments fromD and insert at most two back into D. Therefore, it has O(log n) amortized- runtime if we charge each segment removal to the corresponding insertion.
2) insert(`, low , high): This method inserts into D a segment (or a ray), whose under- lying line is ` and range on the x-axis is [low , high]. We guarantee that the structure maintained by D remains x-monotone after the insertion. Clearly, this function takes O(log n) time.
We initializeD as a single root representing the horizontal line y = ∞. We then sort w1, . . . , wmby non-decreasing order of their lengths (i.e., the length of the corresponding
segment in the primal plane) and insert them into D one by one. When a new wedge, wi = (a∗i, b∗i), comes in, we show how to handle all the possible cases separately according
to the proof of Theorem 6.4. Again, for simplicity, we only consider inserting the left ray, r, of wi, and recall that the finite end-point of r is r0. We also compute the line,
l, that passes through ai and is perpendicular to aibi, and denote its dual point as l∗.
Now, consider the following two cases.
Case 1: l∗ 6∈ r. Choose an auxiliary point r
−∞, which lies on r and has sufficiently
small x-coordinate, to represent the infinite part of r. We then have the following four sub-cases depending on whether r0 and r−∞ are above and/or belowD.
Case 1a: Both of r0 and r−∞ are below D, indicating that r ∩ wj =∅ for all j < i.
(Note that if r∩ wj 6= ∅ it must contain either r0 or r−∞ since l∗ 6∈ r.) In this case, we
simply do remove(−∞, r0.x) followed by insert(r,−∞, r0.x).
Case 1b: r0 is below D and r−∞ is above. This means that if r∩ wj 6= ∅ it must
contain r−∞ and can never contain r0. Thus, r has a unique intersection, γ, with D,
such that the infinite ray γr−∞ is above D and the segment r0γ is below. With this
invariant in hand, we can identify the segment in D that intersects with r, and hence γ, via binary search on those x-coordinates in the range (∞, r0.x]. Once γ is found, we
perform remove(γ.x, r0.x) followed by insert(r, γ.x, r0.x).
Case 1c: r0 is aboveD and r−∞ is below. This case is symmetric to Case 1b and is
thus omitted.
128 entirely above D, or it will intersect D twice, contributing to a new piece of interval on the envelope. We first assume the latter happens. Let α and β be the two intersections and assume α is to the left of β. Then, we claim that ray r−∞α and segment βr0 are
above D, and segment αβ is below. Again, binary search on x-values can be applied to compute α and β, but with a more careful invariant: the underlying wedge with respect to the segment cut by the left boundary always contains the infinite part of r, i.e., r−∞and the underlying wedge cut by the right boundary always contains r0. Once
we find an x-coordinate at which r is below D, we terminate the search and solve two subproblems (one similar to Case 1b and the other similar to Case 1c) to identify α and β, respectively; otherwise, we adjust one of the boundaries accordingly and continue the search. Eventually, the binary search either successfully finds α and β or fails due to being out of range. If α and β exist, we maintain D by calling remove(α.x, β.x) and insert(r, α.x, β.x); otherwise, it means r is completely above D, and therefore, we should leave D unchanged.
Remark. We note that doing binary searches on the above x-coordinates is not as straightforward as searching on a conventional static array because some x-coordinates (i.e., α.x, β.x, and γ.x) are not known beforehand and thus must be computed and maintained dynamically. Therefore, a dynamic data structure must be applied here, which unavoidably introduces an extra O(log m) factor. Formally, we use an order statistic tree [24],OS, to maintain all the x-coordinates as well as their ranks. To do a binary search for values in OS ranging from [xlow, xhigh], we instead do a binary search
on their ranks. It is clear that each binary search takes at most O(log(rank (xhigh)−
rank(xlow) + 1)) = O(log m) steps. In each step, we first do an inverse query on OS to
retrieve the x-value with the middle rank and then queryD with it to decide whether we should shift the left or the right boundary. Both queries can be answered in O(log m) time, and therefore, each binary search takes O(log2m) time.
Case 2: l∗ ∈ r. We first check whether l∗ is above or below D. If below, none of r ∩ wj, j < i, contains l∗ and it essentially boils down to Case 1. Otherwise, l∗
breaks the problem into two subproblems, i.e., inserting ray l∗r−∞ and segment l∗r0,
respectively. We only show how to handle the latter. If r0 is belowD, l∗r0 will have a
unique intersection, γ, withD such that segment l∗γ is above and segment γr
0 is below
a case similar to Case 1d.
Nevertheless, either case involves O(1) number of tree traversals, remove/insert operations, and binary searches. Therefore, inserting w1, . . . , wm into D in total takes
O(m(log m + log2m)) = O(m log2m) = O(n log2n) time. To construct the entire
subdivision, one can explicitly save all the segments (and their corresponding wedges) generated throughout the entire algorithm and build a point location structure [52] to support logarithmic-time query. There are at most O(n) segments according to Lemma 6.4, resulting in an O(n log n) (resp. O(n)) overhead in time (resp. space). Therefore, the total preprocessing time is O(n log2n) and we only use linear space.