sweep1.w
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:40k
开发平台:

MultiPlatform

  1. documentstyle[11pt,comments,a4]{cweb}
  2. voffset=-0.5cm
  3. textwidth 14cm
  4. oddsidemargin          0.4cm
  5. evensidemargin         1.4cm
  6. marginparwidth 1.9cm
  7. marginparsep 0.4cm
  8. marginparpush 0.4cm
  9. topmargin 0cm
  10. headsep 1.5cm
  11. textheight 21.5cm
  12. footskip 2.2cm
  13. input transfig
  14. input papermacros
  15. begin{document}
  16. renewcommand{thefootnote}{fnsymbol{footnote}}
  17. title{Implementation of a Sweep Line Algorithm for the\
  18.        Straight Line Segment Intersection Problem}
  19. author{Kurt Mehlhorn and Stefan N"aher\
  20.        {footnotesize  Max-Planck-Institut f"ur Informatik,}\[-0.7ex]
  21.        {footnotesize 66123 Saarbr"ucken, Germany}}
  22.  
  23.         date{} 
  24.         maketitle
  25. @i typnamen
  26. @* Abstract.
  27. We describe a robust and efficient implementation of the Bentley-Ottmann 
  28. sweep line algorithm cite{Bentley-Ottmann} based on the LEDA library
  29. of efficient data types and algorithms cite{LEDA-Paper}. The program 
  30. computes the planar graph $G$ induced by a set $S$ of straight line segments 
  31. in the plane. The nodes of |G| are all endpoints and all proper intersection 
  32. points of segments in |S|. The edges of |G| are the maximal relatively open 
  33. subsegments of segments in |S| that contain no node of |G|. All edges are
  34. directed from left to right or upwards.
  35. The algorithm runs in time $O((n+s)log n)$ where $n$ is the number of 
  36. segments and $s$ is the number of vertices of the graph $G$. The implementation
  37. is based on the basic geometric types |rat_point| and |rat_segment| of LEDA.
  38. These types represent two-dimensional points and segments with rational
  39. coordinates using exact arithmetic for the realization of all geometric 
  40. primitives. The overhead of the exact arithmetic is reduced by using floating 
  41. point filters (cf. cite{Fortune-vanWyk, LEDA-Geometry}).
  42. tableofcontents
  43. @* Introduction.
  44. Let $S$ be a set of $n$ straight-line segments in the plane and let $G(S)$
  45. be the graph induced by $S$. The vertices of $G(S)$ are all endpoints of
  46. segments in $S$ and all intersection points between segments in $S$. The edges 
  47. of $G$ are the maximal relatively open and connected subsets of segments in
  48. $S$ that contain no vertex of $G(S)$. Figure ref{example} shows an example.
  49. Note that the graph $G(S)$ contains no parallel edges even if $S$ contains segments that overlap.
  50. begin{figure}
  51. begin{center}
  52. input{figures/introfig.tex}
  53. caption{label{example}A set $S$ of segments and the induced planar graph.}
  54. end{center}
  55. end{figure}
  56. Bentley and Ottmann cite{Bentley-Ottmann} have shown how to compute $G(S)$
  57. in time $O((n+m)log n)$ where $m$ is the number of pairs of intersecting
  58. segments in $S$. The algorithm is based on the plane-sweep paradigm. We
  59. refer the reader to cite[section VIII.4]{Mehlhorn-book}
  60. cite[section 7.2.3]{Preparata-Shamos}, and 
  61. cite[section 35.2]{Cormen-Leiserson-Rivest}
  62. for a discussion of the plane sweep paradigm.
  63. In this paper we describe an implementation of the Bentley-Ottmann algorithm. 
  64. More precisely, we define a function
  65. begin{center}
  66.   |sweep_segments(const list<rat_segment>& L,GRAPH<rat_point,rat_segment>& G)|
  67. end{center}
  68. that takes a list $L$ of |rat_segment|s (segments with rational coordinates)
  69. and computes the graph $G$ induced by it. For each vertex $v$ of $G$ it also 
  70. computes its position in the plane, a |rat_point| (a point with rational 
  71. coordinates) and for each edge $e$ of $G$ it computes one of the |rat_segment|s
  72. containing it. The algorithm is based on the LEDA platform for combinatorial 
  73. and geometric computing cite{LEDA-Paper,LEDA-Manual}. 
  74. In LEDA a |rat_segment| is specified by its two endpoints (of type |rat_point|)
  75. and a |rat_point| is specified by its homogeneous coordinates $(X,Y,W)$ of 
  76. type |integer|. The type |integer| is the LEDA type of arbitrary precision 
  77. integers.  Types |rat_point| and |rat_segment| 
  78. -->
  79. --> schreib was ueber rat_point, rat_segment, etc
  80. --> orientation, ...
  81. -->
  82. We want to stress that the implementation makes no assumptions
  83. about the input, in particular, segments may have length zero, may be
  84. vertical or may overlap, several segments may intersect in the same point, 
  85. endpoints of segments may lie in the interior of other segments, dots .
  86. We have achieved this generality by following two principles.
  87. begin{itemize}
  88. item
  89. Treat degeneracies as first class citizens and not as an afterthought
  90. cite{Burnikel-et-al}. In particular, we reformulated the plane-sweep
  91. algorithm so that it can handle all geometric situations. The details will
  92. be given in section ref{Algorithm}. The reformulation makes the 
  93. description of the algorithm shorter since we do not distinguish between
  94. three kinds of events but have only one kind of event and it also makes the 
  95. algorithm faster. The algorithm now runs in time $O((n+s)log n)$ where
  96. $s$ is the number of vertices of $G$. Note that $sleq n+m$ and that $m$
  97. can be as large as $s^2$. The only previous algorithm that could handle all
  98. degeneracies is due to Myers cite{Myers}. Its expected running time for
  99. random segments is $O(n log n + m)$ and its worst case running time is
  100. $O((n + m) log n)$.
  101. item
  102. Evaluate all geometric tests exactly. This is achieved by using the LEDA
  103. basic objects |rat_point| and |rat_segment|. In the implementation
  104. of these types, LEDA uses arbitrary precision integer arithmetic for all 
  105. geometric computations. So all tests are computed exactly and we do not have 
  106. to worry about numerical precision. Of course, there is an overhead of 
  107. arbitrary precision integer arithmetic. In order to keep the overhead small
  108. LEDA uses a floating point filter 
  109. following the suggestion of Fortune and van Wyk cite{Fortune-vanWyk}, i.e., 
  110. all tests are first performed using floating point arithmetic and only if the 
  111. result of the floating point computation is inconclusive the costly exact
  112. computation is performed (cf. cite{LEDA-Geometry} for details). 
  113. end{itemize}
  114. This paper is structured as follows. In section ref{Algorithm} we describe the
  115. (generalized) plane-sweep algorithm. Section ref{Implementation}
  116. and ref{geometric primitives} give the details of the implementation: the 
  117. former section describes the combinatorial part and the latter section describes
  118. the geometric primitives. Section ref{experiments} contains some experimental 
  119. results.
  120. @* The Algorithm. 
  121. label{Algorithm}
  122. In the sweep-line paradigm a vertical line is moved from left to right across 
  123. the plane and the output (here the graph $G(S)$) is constructed incrementally as
  124. it evolves behind the sweep line. One maintains two data structures to keep the
  125. construction going: The so-called {em Y-structure} contains the intersection
  126. of the sweep line with the scene (here the set $S$ of line segments) and the
  127. so-called {em X-structure} contains the events where the sweep has to be
  128. stopped in order to add to the output or to update the $X$- or $Y$-structure.
  129. In the line segment intersection problem an event occurs when the sweep line
  130. hits an endpoint of some segment or an intersection point. When an event
  131. occurs, some nodes and edges are added to the graph $G(S)$, the $Y$-structure
  132. is updated, and maybe some more events are generated. When the input is in
  133. general position (no three lines intersecting in a common point, no endpoint
  134. lying on a segment, no two endpoints or intersections having the same
  135. $x$-coordinate, no vertical lines, no overlapping segments) then at most one
  136. event can occur for each position of the sweep line and there are three clearly
  137. distiguishable types of events (left endpoint, right endpoint, intersection)
  138. with easily describable associated actions, cf. 
  139. cite{Mehlhorn-book}(section VIII.4).
  140. We want to place no restrictions on the input and therefore need to proceed
  141. slightly differently. We now describe the required changes.
  142. We define the sweep line by a point $p_sweep = (x_sweep, y_sweep)$. Let
  143. $epsilon$ be a positive infinitesimal (readers not familiar with
  144. infinitesimals may think of $epsilon$ as an arbitrarily small positive real).
  145. Consider the directed line $L$ consisting of a vertical upward ray ending in
  146. point $(x_sweep + epsilon, y_sweep + epsilon)$ followed by a horizontal
  147. segment ending in $(x_sweep - epsilon, y_sweep + epsilon)$ followed by a
  148. vertical upward ray. We call $L$ the {em sweep line}. Note that no endpoint
  149. of any segment lies on $L$, that no two segments of $S$ intersect $L$ in the
  150. same point except if the segments overlap, and that no non-vertical segment
  151. of $S$ intersects the horizontal part of $L$. All three properties follow from
  152. the fact that $epsilon$ is arbitrarily small but positive. Figure ref{the
  153. sweep line} illustrates the definition of $L$ and the data structures used in
  154. the algorithm: The $Y$-structure, the $X$-structure, and the graph |G|.
  155. begin{figure}
  156. begin{center}
  157. input{figures/sw2fig.tex}
  158. caption{label{the sweep line}A scene of 9 segments. The segments $s_1$ and
  159. $s_8$ overlap. The $Y$-structure contains segments $s_1$, $s_2$, $s_9$, $s_4$,
  160. and $s_3$ and the $X$-structure contains points $a$, $b$, $c$, $d$, $e$, $f$,
  161. $g$, $h$, and $i$. An item in the $X$-structure containing point
  162. $p$
  163. is denoted $xit_p$ and an item in the $Y$-structure containing segment $s_i$
  164. is denoted $sit_i$. The vertices of the graph $G$ are shown as full circles.}
  165. end{center}
  166. end{figure}
  167. The $Y$-structure contains all
  168. segments intersecting the sweep line $L$ ordered as their intersections with
  169. $L$ appear on the directed line $L$. For segments intersecting $L$ in the same
  170. point (these segments necessarily have the same underlying line) only the
  171. segment extending further to the right is stored in the $Y$-structure. 
  172. In the example of Figure ref{the sweep line} the sweep line intersects the
  173. segments $s_8$, $s_1$, $s_2$, $s_9$, $s_4,$ and $s_3$. The segments $s_8$ and
  174. $s_1$
  175. intersect $L$ in the same point and $s_1$ extends further to the right. Thus
  176. $s_1$ is stored in the $Y$-structure and $s_8$ is not. The $Y$-structure
  177. therefore consists of five items, one each for segments $s_1$,$s_2$, $s_9$,
  178. $s_4,$ and
  179. $s_3$.
  180. The $X$-structure is a sorted sequence.
  181. It contains an item for each point in $Stcup Ecup I$, where $St$ is the set
  182. of all start points of segments that lie to the right of $L$, $E$ is the set of
  183. all endpoints of segments that intersect $L$, and $I$ is defined as follows.
  184. Every point in $I$ is the intersection $scap s'$ of two segments $s$ and $s'$
  185. adjacent in the $Y$-structure that lies to the right of the sweep line. The ordering of
  186. the points in the $X$-structure is the lexicographic ordering, i.e.,
  187. $(x,y)$ is before $(x',y')$ if either $x<x'$ or $x=x'$ and $y<y'$.
  188. In the example of Figure ref{the sweep line} we have $St = {a,d,e},
  189. E = {b,c,f,e,g,i,h}$ and $I ={f,a}$. The $X$-structure 
  190. therefore
  191. contains 9 items, one each for points |a|, |b|, |c|, |d|, |e|, |f|, |g|, 
  192. |h|, and |i|.
  193. We next define the informations associated with the items of both structures.
  194. These informations serve to link the items in the $X$-structure with the items
  195. in the $Y$-structure and vice versa. In particular, any item in the
  196. |X|-structure is a pair $<p,sit>$ where |p| is a point and |sit| is either
  197. |nil| or an item in the |Y|-structure and any item in the |Y|-structure 
  198. is a pair $<s,xit>$ where |s| is a segment and |xit| is either |nil|
  199.  or an item in the |X|-structure. Let
  200. $<p,sit>$ be any item in the $X$-structure. If $pin Icup E$ then $sit$ is an
  201. item in the $Y$-structure such that the segment associated with $sit$ contains
  202. $p$. If $pin Stsetminus (Icup E)$ then $sit = nil$. Next consider an item
  203. $<s,xit>$ in the
  204. $Y$-structure and let $s'$ be the segment associated with the successor
  205. item in the $Y$-structure. If $scap s'$ exists and lies to the right of the
  206. sweep line then $xit$ is an item in the $X$-structure and $scap s'$ is the
  207. point associated with that item. If $scap s'$ either does not exist or does
  208. not lie to the right of $L$ then $xit = nil$.
  209. In our example, the $Y$-structure contains the items $<s_1,xit_f>, <s_2,nil>$,
  210. $<s_9,nil>, <s_4,xit_a>$ and $<s_3,nil>$ where $xit_a$ and $xit_f$ are the
  211. items
  212. of the $X$-structure with associated points $a$ and $f$ respectively. Let's
  213. turn to the items of the $X$-structure next. All items except $<d,nil>$ point
  214. back to the $Y$-structure. If $sit_i$ denotes the item $<s_i$,...$>$, $iin%
  215. {1,2,9,4,3}$, of the $
  216. Y$-structure then the items of the $X$-structure are $<a,sit_4>,
  217. <b,sit_4>$, $<c,sit_1>, <d,nil>, <e,sit_9>, <f,sit_1>, <g,sit_2>, <h,sit_3>$
  218. and $<i,sit_1>$.
  219. The graph $G$ is the part of $G(S)$ to the left of $L$. With each vertex of
  220. $G$ we store its position and with each edge of $G$ we store a segment
  221. containing it. For each segment $s$ contained in the $Y$-structure we store 
  222. the rightmost vertex of $G$ lying on $s$.
  223. We can now give the details of the algorithm. Initially, $G$ and the
  224. $Y$-structure are empty, and the $X$-structure contains the left endpoints of
  225. all segments in $S$.
  226. In order to process an event we proceed as follows. Let $<p,sit>$ be the first
  227. item in the $X$-structure. We may assume inductively that all invariants hold
  228. for $p_sweep = (p.x,p.y-2epsilon)$. Note that this is true initially, i.e.,
  229. before the first event is removed from the $X$-structure. We now show how to
  230. establish the invariants for $p = p_sweep$. We proceed in seven steps.
  231. begin{enumerate}
  232. item
  233.   We add a node $v$ at position $p$ to our graph $G$.
  234. item
  235.   We determine all segments in the $Y$-structure containing the point $p$.
  236.   These segments form a possibly empty subsequence of the $Y$-structure.
  237. item
  238.   For each segment in the subsequence we add an edge to the graph $G$.
  239.   Its right endpoint is $v$ and its other endpoint is the vertex stored 
  240.   with the segment $s$.
  241. item
  242.   We delete all segments ending in $p$ from the $Y$-structure.
  243. item
  244.   We reverse the order of the subsequence in the $Y$-structure. This amounts to
  245.   moving the sweep line across the point $p$.
  246. item
  247.   We add all segments starting in $p$ to the $Y$-structure and then associate
  248.   the node $v$ with all segments in the $Y$-structure containing $v$.
  249. --> ACHTUNG HIER HAT SICH WAS GEAENDERT
  250. -->
  251. --> If a
  252. --> newly inserted segment is collinear to an already existing segment
  253. --> we make sure to only keep the segment extending further to the right.
  254. -->
  255. -->
  256. item
  257.   We update the events associated with the items of the $Y$-structure. We
  258.   remove the events associated with the predecessor of the subsequence and
  259.   the last item of the subsequence and we test whether segments becoming
  260.   neighbors in the $Y$-structure intersect and generate new events if necessary.
  261. end{enumerate}
  262. This completes the description of how to process the event $<p,...>$. The
  263. invariants now hold for $p_sweep = p$ and hence also for
  264. $p_sweep = (p'.x,p'.y-2epsilon)$ where $<p',...>$ is the new first element of
  265. the $X$-structure.
  266. @* The Implementation. 
  267. label{Implementation}
  268. The implementation follows the algorithm closely. 
  269. We use sorted sequences, graphs, points and segments with rational
  270. coordinates, and integers of arbitrary precision from LEDA.
  271. -->
  272. --> maps
  273. --> p_queues
  274. -->
  275. We have to include the corresponding header files.
  276. @<include statements@> =
  277. #include <LEDA/sortseq.h>
  278. #include <LEDA/graph.h>
  279. #include <LEDA/rat_point.h>
  280. #include <LEDA/rat_segment.h>
  281. #include <LEDA/integer.h>
  282. #include <LEDA/p_queue.h>
  283. #include <LEDA/map.h>
  284. #include <math.h>
  285. @
  286. Let us briefly explain these types; for a detailed discussion we refer
  287. the reader to the LEDA manual cite{LEDA-Manual}. |integer| is the type of 
  288. arbitrary precision integers.
  289. The types |rat_point| and |rat_segment| realize points and segments in the 
  290. plane with rational coordinates. A |rat_point| is specified by its homogeneous
  291. coordinates of type |integer|. If |p| is a |rat_point| then |p.X()|, |p.Y()|, 
  292. and |p.W()| return its homogeneous coordinates. If |x|, |y|, and |w| are of
  293. type |integer| with $wneq 0$ then |rat_point(x,y)| and |rat_point(x,y,w)| 
  294. create the |rat_point| with homogeneous coordinates |(x,y,1)| and |(x,y,w)| 
  295. respectively. A |rat_segment| is specified by its two endpoints; so if 
  296. |p| and |q| are |rat_point|s then |rat_segment(p,q)| is the directed
  297. segment with startpoint |p| and endpoint |q|. If |s| is a |rat_segment| then
  298. |s.start()| and |s.end()| return the start- and endpoint of |s| respectively.
  299. %---> orientation
  300. %---> left turn
  301. %---> right turn
  302. %---> compare
  303. %---> intersection
  304. @s K int
  305. @s I int
  306. For any types |K| and |I| the type |sortseq<K,I>| is the type of sorted
  307. sequences of pairs in $Ktimes I$. The type |K| must be linearly ordered 
  308. by a function |compare|, i.e., the function 
  309. |int compare(const K&, const K&)| must be defined for the type |K|
  310. and the relation $<$ on |K| defined by $k_1 < k_2$ iff 
  311. $compare(k_1,k_2) < 0$ is a linear order on |K|. Any object of type
  312. |sortseq<K,I>| is a sequence of items (type |seq_item|) each containing
  313. a pair $Ktimes I$. We use |<k,i>| to denote an item containing the pair
  314. $(k,i)$ and call |k| the key and |i| the information of the item. A sorted 
  315. sequence $<k_1,i_1>$,$<k_2,i_2>$,dots ,$<k_m,i_m>$ has the additional
  316. property that the keys of the item form an increasing sequence, i.e.,
  317. $k_l < k_{l+1}$ for $1leq l<m$.
  318. In our implementation the |X|-structure has type |sortseq<rat_point,seq_item>|
  319. the |Y|-structure has type |sortseq<rat_segment,seq_item>|. We use LEDA's
  320. default linear order for |rat_point| which is the lexicographic ordering
  321. of the cartesian coordinates. LEDA has already defined a |compare| function
  322. realizing this linear order. If |p| and |q| are points with cartesian 
  323. coordinates |px|, |py|, |qx|, and |qy| respectively then
  324. [ compare(p,q) = left {
  325.                   begin{array}{rl}
  326.   -1 & mbox{ if }px<qxmbox{ or }px=qxmbox{ and }py<qy\
  327.   0  & mbox{ if }px=qxmbox{ and }py=qy\
  328.   +1 & mbox{ otherwise, }
  329.   end{array}
  330.   right . 
  331. ]
  332. We will later define a linear order for |rat_segment| by writing
  333. an appropriate compare function.
  334. If |s1| and |s2| are segments intersecting the sweep line |L| then
  335. |compare(s1,s2) = -1| if $s1cap L$ precedes $s2cap L$ on |L|,
  336. |compare(s1,s2) = 0| if $s1cap L = s2cap L$, and
  337. |compare(s1,s2) = +1| if $s1cap L$ comes after $s2cap L$.
  338. It is important to observe that the compare function for segments
  339. changes as the sweep progresses. What does it mean then that the keys of the 
  340. items in a sorted sequence form an increasing sequence? LEDA requires 
  341. that whenever a lookup or insert operation is applied to a sorted
  342. sequence the sequence must be sorted with respect to the current 
  343. compare function. The other operations may be applied even if the 
  344. sequence is not sorted. What operations are available?
  345. Let |S| be a sorted sequence of type |sortseq<K,I>| and let |k| 
  346. and |i| be of type |K| and |I| respectively. The operation 
  347. |S.lookup(k)| returns the item $it = <k,.>$ in |S| with key |k| if there
  348. is such an item and returns |nil| otherwise. If |S.lookup(k)==nil|
  349. then |S.insert(k,i)| adds a new item |<k,i>| to |S| and returns
  350. this item. If |S.lookup(k)==it| then |S.insert(k,i)| changes the
  351. information in the item |it| to |i|. If $it=<k,i>$ is an item of |S|
  352. then |S.key(it)| and |S.inf(it)| return |k| and |i| respectively and
  353. |S.succ(it)| and |S.pred(it)| return successor and predecessor item
  354. of |it| respectively; the latter operations return |nil| if these
  355. items do not exist. The operation |S.min()| returns the first item
  356. of |S|, |S.empty()| returns true if |S| is empty and false otherwise. 
  357. Finally, if |it1| and |it2| are items of |S| with |it1| before |it2|
  358. then |S.reverse_items(it1,it2)| reverses the subsequence of |S| 
  359. starting at item |it1| and ending at item |it2|. The requirement for
  360. this operation is that the sequence |S| is sorted with respect to
  361. the current compare function after the operation.
  362. The graph |G| to be constructed has type |GRAPH<rat_point,rat_segment>|, i.e.,
  363. it is a directed graphs where a |rat_point| (|rat_segment|) is associated with
  364. each node (edge) of the graph. If |p| is a |rat_point| then
  365. |G.new_node(p)| adds a new node to |G|, associates |p| with the node,
  366. and returns the new node. If |v| and |w| are nodes of |G| and |s|
  367. is a |rat_segment| then |G.new_edge(v,w,s)| adds the edge |(v,w)| to |G|, 
  368. associates |s| with the edge, and returns the new edge.
  369. %---> map
  370. %---> hash
  371. @* The Basic Program Structure.
  372. Our program has the following structure.
  373. @c
  374. @<include statements@>@;
  375. @<geometric primitives@>@;
  376. void sweep(list<rat_segment>& S, GRAPH<rat_point,rat_segment>& G)
  377. {
  378.  @<local declarations @>@;
  379.  @<initialization @>@;
  380.  @<sweep @>@;
  381. }
  382. @ In the local declarations section of function |sweep| we introduce 
  383. the data types for the event queue (|X_structure|) and for the sweep 
  384. line (|Y_structure|). For the X-structure we use a sorted sequence of 
  385. points with the lexicographic ordering of their coordinates, and for 
  386. the Y-structure a sorted sequence of segments with the linear order 
  387. defined by the sequence intersections of the segments with the sweep line 
  388. at its current position (|p_sweep|) from bottom to top.
  389. The X-structure contains all so far 
  390. known event points right and above of the current sweep line position 
  391. (|p_sweep|), i.e. all start and end points of segments and intersections 
  392. of segments being adjacent in the sweep line. The X-structure associates 
  393. with each event point |p| an item of the Y-structure (|seq_item|) as 
  394. information; if there are only starting segments at |p| the information is 
  395. |nil|, otherwise the information is an item in the Y-structure containing one 
  396. of the segments passing through or ending in |p|. 
  397. Vice versa we associate with each 
  398. segment |s| in the Y-structure that intersects its successor in some point |p| 
  399. the corresponding item |<p,...>| in the X-structure as information.
  400. We call this item the {sl current intersection item} of |s|. If |s| does not 
  401. intersect its successor its current intersection item is |nil|.
  402. Finally, we store with each segment |s| the last created node
  403. of the output graph |last_node| lying on |s|.
  404. @<local declarations @> =
  405. sortseq<rat_point,seq_item> X_structure;
  406. sortseq<rat_segment,seq_item> Y_structure;
  407. @ We now come to the initialization of the data structures. 
  408. We first compute a big integer |Infinity| that can be used as a safe 
  409. approximation for $infty$. We start the sweep at $(-infty,-infty)$. 
  410. At its initial position the sweep line (i.e. the Y-structure)
  411. contains two infinitely long horizontal segments (|lowersentinel| and 
  412. |uppersentinel|) with $y$-coordinates $-infty$ and $+infty$ respectively, 
  413. and the output graph |G| is empty. 
  414. We create for each |rat_segment| in |S| the corresponding |mySegment| 
  415. (reorienting if necessary) and insert its left endpoint together with the 
  416. information |nil| into the $X$-structure. We use the fact that a sorted 
  417. sequence contains at most one item for every key and that a second insert 
  418. operation with the same key only changes the information of the item to make 
  419. the left endpoints of all segments unique. This makes equality tests between 
  420. endpoints of segments much cheaper, since now the |myPoint| pointers can be 
  421. compared directly (using the |==| operator) instead of having to call an 
  422. expensive compare function. 
  423. Finally, we sort all segments according to their left endpoints into
  424. a list |S_Sorted| by calling the LEDA list sorting operation
  425. |S_Sorted.sort(cmp_seg)|. Here |cmp_seg| is a compare function
  426. defined in section ref{geometric primitives}.
  427. @<initialization @> =
  428. @ We now come to the heart of procedure sweep: the processing of events. Let
  429. |event = <p,sit>| be the first event in the X-structure and assume 
  430. inductively that our data structure is correct for 
  431. $p_sweep = (p.x,p.y-2epsilon)$. Our goal is to to change |p_sweep| to |p|, 
  432. i.e., move the sweep line across the point |p|. We perform the following 
  433. actions.
  434. We first add a vertex |v| with position |p| to the output graph |G|.
  435. Then, we handle all segments passing through or ending at |p_sweep|. 
  436. Finally, we insert all segments starting
  437. at |p_sweep| into the Y-structure, check for possible intersections
  438. between pairs of segments now adjacent in the Y-structure, and update 
  439. the  X-structure. After having processed the |event| we delete it from 
  440. the X-structure.
  441. @<sweep @> =
  442. while( ! X_structure.empty() )
  443.   seq_item event = X_structure.min();
  444.   seq_item sit = X_structure.inf(event);
  445.   p_sweep = X_structure.key(event);
  446.   node v = G.new_node(p_sweep); 
  447.   @<handle passing and ending segments @>@;
  448.   @<insert starting segments @>@;
  449.   @<compute new intersections @>@;
  450.   X_structure.del_item(event);
  451. }
  452. @ label{misuse of compare}
  453. We first handle all segments passing through or ending in point |p|. 
  454. How can we find them?
  455. Recall that the current event is $<p,sit>$ and that $sit not= nil$ iff 
  456. $p in I cup E$. If $sit not= nil$ then $p$ is contained in the segment
  457. associated with |sit|. If $sit = nil$ then $p in St setminus (I cup E)$.
  458. In this case there is at most segment in the Y-structure containing $p$. 
  459. We may determine this segment by looking up the zero-length segment 
  460. |(p->pt,p->pt)| in the Y-structure. We explain in section 
  461. ref{explanation of misuse} why this works.
  462. After the lookup we have either $sit = nil$ and then no segment in the 
  463. Y-structure contains |p| or $sit not= nil$ and then the segment associated 
  464. with $sit$ contains $p$. In the latter case we determine all such segments 
  465. and update the graph $G$ and the Y-structure.
  466. We also declare two items |sit_pred| and |sit_succ| and initialize them to 
  467. |nil|. If the $Y$-structure contains a segment containing |p| then |sit_pred| 
  468. and |sit_succ| will be the set to the predecessor and successor item of the
  469. subsequence of segments containing |p|, otherwise they stay |nil|.
  470.  
  471. Taking |sit| as an entry point into the Y-structure we determine all segments
  472. incident to |p| from the left or from below. These segments form a subsequence 
  473. of the Y-structure. Let |sit_first| and |sit_last| denote the first and the 
  474. last item of the subsequence and let |sit_pred| be the predecessor of 
  475. |sit_first| and |sit_succ| the successor of |sit_last|. Note that the 
  476. information of all items in this subsequence is equal to the current
  477. event item |event|, except for |sit_last| whose information is either |nil|
  478. or a different item in the X-structure resulting from an intersection
  479. with |sit_succ|. 
  480. Note also that the identification of the subsequence of segments incident to 
  481. $p$ takes constant time per element of the sequence. Moreover, the constant 
  482. is small since the test whether $p$ is incident to a segment involves no 
  483. geometric computation but only equality tests between items.
  484. Note finally that the code is particularly simple due to our sentinel segments:
  485. |sit_first| can never be the first item of the Y-structure and |sit_last|
  486. can never be the last.
  487. We can now add edges to the graph |G|. For each segment in the subsequence 
  488. between |sit_first| and |sit_last| inclusive we construct an edge. Let |sit| be 
  489. any such item and let |s| be the segment associated with |sit|. We construct an 
  490. edge connecting |s -> last_node| and |v| and label it with the segment |s|.
  491. We also either delete the item from the Y-structure (if the segment ends at
  492. |p|) or change its information to |nil| (if the segment does not end at |p|) to
  493. reflect the fact that no intersection event is now associated with the 
  494. segment. In the former case we free the storage reserved for the segment.
  495. At the end we have to update variables |sit_first| and |sit_last|
  496. since the corresponding items may have been deleted.
  497. All segments remaining in the subsequence pass through node |v| and moving 
  498. the sweep line through |p_sweep| inverses the order of the segments in the 
  499. subsequence. The subsequence is non-empty iff |sit_last != sit_pred|.
  500. Reversing the subsequence destroys the adjacency of pairs 
  501. (|sit_pred|,|sit_first|) and (|sit_last|,|sit_succ|) in the |Y|-structure 
  502. and hence we have to set the current intersection event of |sit_pred| and 
  503. |sit_last| (i.e. the associated information in the Y-structure) to |nil|,
  504. decrement the corresponding counters, and delete the items from the 
  505. X-structure if the counters are zero now. If the subsequence is empty we 
  506. only need to change the intersection event associated of |sit_pred| to |nil|.
  507. Finally, we reverse the subsequence by calling
  508. |Y_structure.reverse_items(sit_first,sit_last)|.
  509. @<handle passing and ending segments @> =
  510. @ The last step in handling the event point |p| is to insert all segments 
  511. starting at |p| into the |Y|-structure and to test the new pairs of adjacent
  512. items (|sit_pred|,...) and (...,|sit_succ|) for possible intersections. If
  513. there were no segments passing through or ending in |p| then the items 
  514. |sit_succ| and |sit_pred| are still |nil|  and we have to compute them now.
  515. We use the sorted list |S_Sorted| to find all segments to be 
  516. inserted. As long as the first segment |seg| in |S_Sorted| starts at point |p| 
  517. we remove it from the list, insert it into the |Y|-structure, add its right 
  518. endpoint to the |X|-structure, and set |seg -> last_node| to |v|. If the 
  519. segment has length zero we simply discard it and if |sit_succ| and |sit_pred| 
  520. are still undefined (|nil|) then we use the first inserted segment to define 
  521. them. In this case, we also have to change the possible current intersection
  522. event of |sit_pred| to |nil| since it is no longer adjacent to |sit_succ|.
  523. If all segments starting in |p| have length zero then |sit_succ| and 
  524. |sit_pred| remain undefined. 
  525. We need to say more clearly how to insert a segment |s| into the |Y|-structure.
  526. If the |Y|-structure contains no segment with the same underlying line then we
  527. simply add the segment. Otherwise, let $s'$ be the segment in the |Y|-structure
  528. with the same underlying line. We replace |s| by $s'$ if $s'$ extends further 
  529. to the right than $s$ and do nothing otherwise.
  530. @<insert starting segments @> =
  531. @ After having inserted all segments starting at |p|, we test whether
  532. |sit_succ| (|sit_pred|) intersects its predecessor (successor) in the 
  533. |Y|-structure.
  534. @<compute new intersections @> =
  535. @* Geometric Primitives.
  536. label{geometric primitives}
  537. It remains to define the geometric primitives used in the implementation. We
  538. need three:
  539. begin{itemize}
  540. item
  541.   a compare function for |myPoint|s which orders points according 
  542.   to the lexicographic ordering of their coordinates. It defines the linear 
  543.   order used in the X-structure.
  544. item
  545.   a compare-function for |mySegment|s which given two segments intersecting the
  546.   sweep line $L$ determines the order of the intersections on $L$. It defines 
  547.   the linear order used in the Y-structure.
  548. item
  549.   a function |compute_intersection| that decides whether two segments intersect
  550.   and if so whether the intersection is to the right of the sweep line. If
  551.   both tests are positive it also makes the required changes to the $X$- and
  552.   $Y$-structure.
  553. end{itemize}
  554. @ Next we write the compare function for segments.
  555. @<geometric primitives @> =
  556. // geometric primitives
  557. static POINT p_sweep;
  558. static int   N;
  559. inline int pair(const SEGMENT& p, const SEGMENT& q)
  560. { return  ID_Number(p) * N + ID_Number(q); }
  561. inline int compare(const SEGMENT& s1, const SEGMENT& s2)
  562.   // Precondition: |p_sweep| is identical to the left endpoint of
  563.   // either |s1| or |s2|. This is true since comparisons are only 
  564.   // executed when inserting or looking up new segments.
  565.   if ( identical(p_sweep,s1.start()) )
  566.   { int s = orientation(s2,p_sweep);
  567.     return (s != 0) ? -s : cmp_slopes(s1,s2);
  568.    }
  569.   if ( identical(p_sweep,s2.start()) )
  570.   { int s = orientation(s1,p_sweep);
  571.     return (s != 0) ? s : cmp_slopes(s1,s2);
  572.    }
  573.   error_handler(1,"internal error in sweep");
  574.   return 0; // never reached
  575. }
  576. @ label{explanation of misuse}
  577. What does compare do when one of the segments, say |s1|, has both endpoints 
  578. equal to |p_sweep| and the Y-structure contains 
  579. at most one segment containing |p_sweep|. That's exactly 
  580. the situation in section ref{misuse of compare}. When |s2| 
  581. contains |p_sweep| the underlying lines are found identical and 
  582. compare returns 0. When |s2| does not contain 
  583. |p_sweep| then the underlying lines are declared different. 
  584. Also |s1| is declared vertical and
  585. |s2| is not vertical since it would otherwise contain |p_sweep|. 
  586. We now compare
  587. $ l cap s2$ and |p_sweep| and return the result. We conclude that the call
  588. |Y_structure.locate(s)| where $s$ is the zero-length segment |(p->pt,p->pt)| 
  589. in section ref{misuse of compare} has the desired effect.
  590. @ Finally, we define a function |compute_intersection| that takes an item
  591. |sit0| of the Y-structure and determines whether the segment associated with
  592. |sit0| intersects the segment associated with the successor of |sit0|
  593. right or above of the sweep line. If so it updates the X- and the Y-structure.
  594. The function first tests whether the underlying straight lines intersect right 
  595. or above of the sweep line by comparing their slopes. This test is performed
  596. with floating point arithmetic and repeated with exact arithmetic if the
  597. floating point test gives no reliable result.  If the segments do intersect
  598. right or above of the sweep line it is checked whether the point of 
  599. intersection lies on both segments, i.e., is not larger than the endpoints of 
  600. the segments.
  601. @<geometric ...@>+=
  602. static void compute_intersection(sortseq<POINT,seq_item>& X_structure,
  603.                                  sortseq<SEGMENT,seq_item>& Y_structure,
  604.                                  hash<int,seq_item>& inter_dic,
  605.                                  seq_item sit0)
  606. {
  607.   // Given an item |sit0| in the Y-structure compute the point of 
  608.   // intersection with its successor and (if existing) insert it into 
  609.   // the event queue and do all necessary updates.
  610.   seq_item sit1 = Y_structure.succ(sit0);
  611.   SEGMENT  s0   = Y_structure.key(sit0);
  612.   SEGMENT  s1   = Y_structure.key(sit1);
  613.   // |s1| is the successor of |s0| in the Y-structure, hence,
  614.   // |s0| and |s1| intersect right or above of the sweep line
  615.   // iff |(s0.start(),s0.end(),s1.end()| is not a left turn and 
  616.   // |(s1.start(),s1.end(),s0.end()| is not a right turn.
  617.   // In this case we intersect the underlying lines
  618.   
  619.   if (orientation(s0,s1.end()) >= 0 && orientation(s1,s0.end()) <=0 )
  620.   { hash_item it = inter_dic.lookup(pair(s0,s1));
  621.     if (it != nil)
  622.        { Y_structure.change_inf(sit0,inter_dic.inf(it));
  623.          inter_dic.del_item(it);
  624.         }
  625.     else
  626.        { POINT    q;
  627.          s0.intersection_of_lines(s1,q);
  628.          Y_structure.change_inf(sit0, X_structure.insert(q,sit0));
  629.         }
  630.   }
  631. }
  632. @* Experiments and Efficiency.
  633. label{experiments}
  634. We performed tests on three kinds of test data: 
  635. difficult inputs, random inputs and  hand-crafted examples.
  636. begin{itemize}
  637. item
  638. Difficult inputs:
  639. Let $size$ be a random $k$-bit integer and
  640. let $y = 2size/n$. We intersect $n$ segments where the $i$-th segment 
  641. has endpoints $(size + rx1$, $2 cdot size  -i cdot y + ry1)$ and 
  642. $(3size + rx2$, $2size + i cdot y + ry2)$ where $rx1$, $rx2$, $ry1$, $ry2$ 
  643. are random integers in $[-s,s]$ for some small integer $s$. 
  644. item 
  645. Random inputs: 
  646. We generated $n$ (between 1 and several hundred) segments
  647. with random coordinates between $-size$ and $size$ for some parameter $size$. 
  648. For $size$ we used large values to test the correctness and efficiency of the
  649. floating point filter and the long integer arithmetic and small values to
  650. test our claim that we can handle all degeneracies (a set of 100 segments whose
  651. endpoints have integer coordinates between -3 and +3 is highly degenerate).
  652. item Hand-crafted examples: We handcrafted some examples that exhibited a 
  653. lot of degeneracies. We also asked students to break the code and offered 
  654. DM 100.- for the first counter-example.
  655. end{itemize}
  656. Table ref{difficult} gives the result for the difficult inputs with 
  657. $s=3$, $k=10,15,20,cdots,100$, and $n=100$. It lists the number 
  658. of intersection and the running times
  659. with and without the floating point filter. Furthermore it
  660. gives  the percentage of the comparisons of points in the X-structure 
  661. that were left undecided by the floating point filter (failure
  662. rate) and  the percentage of tests where the floating point computation 
  663. would have decided incorrectly (error rate).
  664. begin{table}
  665. begin{tabular}{rccccc}
  666. $k$ & $|V|$ & without filter &  with filter & failures & errors  \
  667. hline
  668.  10 &  1323 &  0.78 &  0.37  &   0.05% &  0.00% \
  669. end{tabular}
  670. caption{The difficult example with 100 segments.}label{difficult}
  671. end{table}
  672. Comparing the $x$-coordinates of two intersection points is tantamount 
  673. to testing the sign of a fifth degree homogeneous
  674. polynomial in the coordinates of the segment endpoints. These coordinates
  675. are of the form $size + rx$, $3size + rx$, $2size + icdot y + ry$, $2size -i
  676. cdot y + ry$.
  677. Thus, if we write the polynomial in terms of the perturbations $rx$ and
  678. $ry$ we essentially obtain a term of order $size^5$ independent of the
  679. perturbations (this term is actually zero but has maximal size in
  680. intermediate results) plus a term or order $size^4$ times a linear
  681. function in the perturbations plus a term of order $size^3$ times a
  682. quadratic function in the perturbations $cdots$ . Since the input
  683. coordinates are not equal to |size| but vary between $size$ and $3size$
  684. the various terms are actually spread out over some orders of magnitude.
  685. In the floating point filter analysis the error bound $delta$ is about
  686. $3size^5 cdot 2^{-53}$. We conclude that the floating point filter
  687. becomes worthless for $k$ about 50 and that we are starting to loose
  688. the linear terms for $k$ about 40. For smaller $k$ the filter fails
  689. only in those rare cases where the second order term must decide. This is
  690. well reflected in Table ref{difficult}. 
  691. begin{table}
  692. begin{tabular}{rccccc}
  693. $k$ & $|V|$ & without filter & with filter & failures & errors \ 
  694. hline
  695.   10& 1298  & 0.57  & 0.35   &  0.00%  &  0.00% \
  696. end{tabular}
  697. caption{100 random segments, coordinates are random $k$-bit integers.}
  698. label{random}
  699. end{table}
  700. Table ref{random} gives the results for 100 segments whose endpoints have 
  701. random $k$ bit coordinates. The experiments inidicate that the floating point filter reduces the
  702. running time of the program by a factor of 2. 
  703.  
  704. More experiments with different floating
  705. point filters are described in cite{IFIP94}.
  706. @* Conclusion.
  707. We have given an implementation of the Bentley-Ottmann
  708. plane sweep algorithm for line segment intersection. The implementation is
  709. complete and reliable in the sense that it will work for all input instances.
  710. It is asympotically more efficient than previous algorithms for the same task;
  711. its running time  depends on the number of vertices in the intersection
  712. graph and not on the number of pairs of intersecting segments. It also
  713. achieves a low constant factor in its running time by means of a floating
  714. point filter. The use of LEDA makes the implementation of the algorithm short 
  715. and elegant.
  716. newpage
  717. begin{thebibliography}{10}
  718. bibitem{Bentley-Ottmann} 
  719. J.L.~Bentley and T.A.~Ottmann. 
  720. newblock Algorithms for reporting and counting geometric intersections.
  721. newblock {em IEEE Trans. Comput.}, C-28:643--647, 1979.
  722. bibitem{Burnikel-et-al}
  723. C.~Burnikel, K.~Mehlhorn, and S.~Schirra.
  724. newblock On degeneracy in geometric computations.
  725. newblock In {em Proc. of the 5th ACM-SIAM Symp. on Discrete Algorithms},
  726.   pp. 16--23, 1994.
  727. bibitem{Cormen-Leiserson-Rivest}
  728. T.H. Cormen and C.E. Leiserson and R.L. Rivest.
  729. newblock Introduction to Algorithms.
  730. newblock MIT Press/McGraw-Hill Book Company, 1990.
  731. bibitem{Fortune-vanWyk}
  732. S.~Fortune and C.~van Wyk.
  733. newblock Efficient exact arithmetic for computational geometry.
  734. newblock In {em Proc. of the 9th ACM Symp. on Computational Geometry},
  735.   pp. 163--172, 1993.
  736. bibitem{Mehlhorn-book}
  737. K.~Mehlhorn.
  738. newblock Data Structures and Efficient Algorithms.
  739. newblock Springer Publishing Company, 1984.
  740. bibitem{Myers}
  741. E.~Myers.
  742. newblock{An $O(E log E + I)$ expected time algorithm for the planar
  743. segment intersection problem.}
  744. newblock {em SIAM J. Comput.}, pp. 625 --636, 1985.
  745. bibitem{LEDA-Paper}
  746. K.~Mehlhorn and S.~N"aher.
  747. newblock {LEDA}: A library of efficient data types and algorithms.
  748. newblock In {em LNCS}, 379:88--106, 1989.
  749. bibitem{IFIP94}
  750. K.~Mehlhorn and S.~N"aher.
  751. newblock The Implementation of Geometric Algorithms.
  752. newblock 13th World Computer Congress IFIP 94, Elsevier Science B.V., 
  753. Vol. 1, pp. 223--231, 1994.
  754. bibitem{LEDA-Manual}
  755. S.~N"aher.
  756. newblock LEDA Manual.
  757. newblock Technical Report No. MPI--I--93--109.
  758. newblock Max-Planck-Institut f"ur Informatik, 1993.
  759. bibitem{Preparata-Shamos}
  760. F. Preparata and M.I. Shamos.
  761. newblock Computational Geometry: An Introduction.
  762. newblock Springer Publishing Company, 1985
  763. bibitem{Yap-Dube:Exact-Computation}
  764. Ch. Yap and Th. Dub'{e}.
  765. newblock The exact computation paradigm.
  766. newblock In {em Computing in Euclidian Geometry}, World Scientific
  767. Press, 1994. (To appear, 2nd edition).
  768. end{thebibliography}
  769. end{document}