Английская Википедия:Fortune's algorithm
Fortune's algorithm is a sweep line algorithm for generating a Voronoi diagram from a set of points in a plane using O(n log n) time and O(n) space.[1][2] It was originally published by Steven Fortune in 1986 in his paper "A sweepline algorithm for Voronoi diagrams."[3]
Algorithm description
The algorithm maintains both a sweep line and a beach line, which both move through the plane as the algorithm progresses. The sweep line is a straight line, which we may by convention assume to be vertical and moving left to right across the plane. At any time during the algorithm, the input points left of the sweep line will have been incorporated into the Voronoi diagram, while the points right of the sweep line will not have been considered yet. The beach line is not a straight line, but a complicated, piecewise curve to the left of the sweep line, composed of pieces of parabolas; it divides the portion of the plane within which the Voronoi diagram can be known, regardless of what other points might be right of the sweep line, from the rest of the plane. For each point left of the sweep line, one can define a parabola of points equidistant from that point and from the sweep line; the beach line is the boundary of the union of these parabolas. As the sweep line progresses, the vertices of the beach line, at which two parabolas cross, trace out the edges of the Voronoi diagram. The beach line progresses by keeping each parabola base exactly half way between the points initially swept over with the sweep line, and the new position of the sweep line. Mathematically, this means each parabola is formed by using the sweep line as the directrix and the input point as the focus.
The algorithm maintains as data structures a binary search tree describing the combinatorial structure of the beach line, and a priority queue listing potential future events that could change the beach line structure. These events include the addition of another parabola to the beach line (when the sweep line crosses another input point) and the removal of a curve from the beach line (when the sweep line becomes tangent to a circle through some three input points whose parabolas form consecutive segments of the beach line). Each such event may be prioritized by the x-coordinate of the sweep line at the point the event occurs. The algorithm itself then consists of repeatedly removing the next event from the priority queue, finding the changes the event causes in the beach line, and updating the data structures.
As there are O(n) events to process (each being associated with some feature of the Voronoi diagram) and O(log n) time to process an event (each consisting of a constant number of binary search tree and priority queue operations) the total time is O(n log n).
Pseudocode
Pseudocode description of the algorithm.[4]
let <math>\scriptstyle *(z)</math> be the transformation <math>\scriptstyle *(z)=(z_x,z_y+d(z))</math>, where <math>\scriptstyle d(z)</math> is the Euclidean distance between Шаблон:Mvar and the nearest site let Шаблон:Mvar be the "beach line" let <math>\scriptstyle R_p</math> be the region covered by site Шаблон:Mvar. let <math>\scriptstyle C_{pq}</math> be the boundary ray between sites Шаблон:Mvar and Шаблон:Mvar. let <math>\scriptstyle S</math> be a set of sites on which this algorithm is to be applied. let <math>\scriptstyle p_1,p_2,...,p_m</math> be the sites extracted from Шаблон:Mvar with minimal Шаблон:Mvar-coordinate, ordered by Шаблон:Mvar-coordinate let DeleteMin(Шаблон:Mvar) be the act of removing the lowest and leftmost site of Шаблон:Mvar (sort by y unless they're identical, in which case sort by x) let Шаблон:Mvar be the Voronoi map of Шаблон:Mvar which is to be constructed by this algorithm <math>Q \gets {p_1,p_2,\dots,p_m,S}</math> create initial vertical boundary rays <math>\scriptstyle C_{p_1,p_2}^0,C_{p_2,p_3}^0,\dots,C_{p_{m-1},p_m}^0</math> <math>T \gets *(R_{p_1}),C_{p_1,p_2}^0,*(R_{p_2}),C_{p_2,p_3}^0,\dots,*(R_{p_{m-1}}),C_{p_{m-1},p_m}^0,*(R_{p_m})</math> while not IsEmpty(Шаблон:Mvar) do Шаблон:Mvar ← DeleteMin(Шаблон:Mvar) case Шаблон:Mvar of Шаблон:Mvar is a site in <math>\scriptstyle *(V)</math>: find the occurrence of a region <math>\scriptstyle *(R_q)</math> in Шаблон:Mvar containing Шаблон:Mvar, bracketed by <math>\scriptstyle C_{rq}</math> on the left and <math>\scriptstyle C_{qs}</math> on the right create new boundary rays <math>\scriptstyle C_{pq}^-</math> and <math>\scriptstyle C_{pq}^+</math> with bases Шаблон:Mvar replace <math>\scriptstyle *(R_q)</math> with <math>\scriptstyle *(R_q),C_{pq}^-,*(R_p),C_{pq}^+,*(R_q)</math> in Шаблон:Mvar delete from Шаблон:Mvar any intersection between <math>\scriptstyle C_{rq}</math> and <math>\scriptstyle C_{qs}</math> insert into Шаблон:Mvar any intersection between <math>\scriptstyle C_{rq}</math> and <math>\scriptstyle C_{pq}^-</math> insert into Шаблон:Mvar any intersection between <math>\scriptstyle C_{pq}^+</math> and <math>\scriptstyle C_{qs}</math> Шаблон:Mvar is a Voronoi vertex in <math>\scriptstyle *(V)</math>: let Шаблон:Mvar be the intersection of <math>\scriptstyle C_{qr}</math> on the left and <math>\scriptstyle C_{rs}</math> on the right let <math>\scriptstyle C_{uq}</math> be the left neighbor of <math>\scriptstyle C_{qr}</math> and let <math>\scriptstyle C_{sv}</math> be the right neighbor of <math>\scriptstyle C_{rs}</math> in Шаблон:Mvar if <math>\scriptstyle q_y = s_y</math>, create a new boundary ray <math>\scriptstyle C_{qs}^0</math> else if Шаблон:Mvar is right of the higher of Шаблон:Mvar and Шаблон:Mvar, create <math>\scriptstyle C_{qs}^+</math> else create <math>\scriptstyle C_{qs}^-</math> endif replace <math>\scriptstyle C_{qr},*(R_r),C_{rs}</math> with newly created <math>\scriptstyle C_{qs}</math> in Шаблон:Mvar delete from Шаблон:Mvar any intersection between <math>\scriptstyle C_{uq}</math> and <math>\scriptstyle C_{qr}</math> delete from Шаблон:Mvar any intersection between <math>\scriptstyle C_{rs}</math> and <math>\scriptstyle C_{sv}</math> insert into Шаблон:Mvar any intersection between <math>\scriptstyle C_{uq}</math> and <math>\scriptstyle C_{qs}</math> insert into Шаблон:Mvar any intersection between <math>\scriptstyle C_{qs}</math> and <math>\scriptstyle C_{sv}</math> record Шаблон:Mvar as the summit of <math>\scriptstyle C_{qr}</math> and <math>\scriptstyle C_{rs}</math> and the base of <math>\scriptstyle C_{qs}</math> output the boundary segments <math>\scriptstyle C_{qr}</math> and <math>\scriptstyle C_{rs}</math> endcase endwhile output the remaining boundary rays in Шаблон:Mvar
Weighted sites and disks
Additively weighted sites
As Fortune describes in ref.,[1] a modified version of the sweep line algorithm can be used to construct an additively weighted Voronoi diagram, in which the distance to each site is offset by the weight of the site; this may equivalently be viewed as a Voronoi diagram of a set of disks, centered at the sites with radius equal to the weight of the site. the algorithm is found to have <math>O(n\log(n))</math> time complexity with n being the number of sites according to ref.[1]
Weighted sites may be used to control the areas of the Voronoi cells when using Voronoi diagrams to construct treemaps. In an additively weighted Voronoi diagram, the bisector between sites is in general a hyperbola, in contrast to unweighted Voronoi diagrams and power diagrams of disks for which it is a straight line.
References
External links
- Steven Fortune's C implementation
- Fortune's Voronoi algorithm implemented in C++
- Fortune's algorithm implemented in JavaScript
- ↑ 1,0 1,1 1,2 Шаблон:Citation Section 7.2: Computing the Voronoi Diagram: pp.151–160.
- ↑ Шаблон:Citation.
- ↑ Steven Fortune. A sweepline algorithm for Voronoi diagrams. Proceedings of the second annual symposium on Computational geometry. Yorktown Heights, New York, United States, pp.313–322. 1986. Шаблон:ISBN. ACM Digital LibrarySpringerLink
- ↑ Шаблон:Citation.