A Voronoi diagram is a decomposition of space, here a 2d plane, on a nearest neighbour basis. The diagram splits the plane in regions, each corresponding to a site (a point of interest), and containing all the points closer to this site than to any other.

What got me in Voronoi mood however is seeing this this algorithmic collage by Santiago Ortiz from Bestiario. The work’s sheer visual impact shows off the one quality of Voronoi diagrams I appreciate the most – they look awesome. Watching the masks move for a couple of minutes got me terribly into porting Steve Fortune’s algorithm for Voronoi decomposition: I had to see for myself how much stuff could happen on the screen before the player choked.

Fortune’s algorithm

Fortune’s algorithm, ideally, computes a Voronoi diagram in O(NlogN) time, where N is the number of sites, or the minimum possible time for the job, as O(NlogN) is the time-complexity of optimal sorting algorithms. It sweeps through the plane, maintaining a front of parabolas that progressively traces out the diagram, by spliting and adding curves for each site encountered, and removing arcs whenever a region vertex is determined with certainty. The Wikipedia article has it all explained pretty well, but if you need additional info, give this and this articles a try.

I began with this c++ implementation, which is a simplified take on the algorithm. The latter uses a binary tree for the composition of the beachline, whilst here we’ve got a double linked list. However, I do think that the double-link approach would do better for most visual applications in flash, where the cost of not having quick lookup of beachline parabolas might be offset by not having to reogranise the tree, and by the low overall number of particles. I ended up modifying and optimising most of the code however, and I bet this is the reason for the artifacts that show up every now and then in the last of the three demos.

Then 2000 points going around with their speed determined by the values of an image:

Finally, a simple audio visualiser:

Anyway, this really is just a study of how quickly the regions of a diagram can shape up without cheating. There is no bounding box intersection, nor sophisticated output options. Clearly, output of an optimal and informative data structure will be worth the performance kick, and if I get to do my graph theory homework, I’ll be coming back to this.

Implementations

Fortune’s algorithm is already well implemented and made available by astatic, also nodename shows it off with his Voronoi toy, even though you don’t see the sources. You get a different tool for the same job by HIDIHO!, he goes through Delaunay triangulation, and then translates to a Voronoi decomposition, the two being dual graphs.

26 Responses to “Speedy Voronoi diagrams in as3/flash”

I look forward to reading this code. I didn’t know about the C++ implementation. The algorithm as described in Fortune’s paper generalizes easily to weighted sites, but it’s hard for me to see how his own C code would support that.

This is really cool, and very useful. But… looking at the source code, my head exploded. This source code makes me feel very stupid… is it strange? I’m kind of new to flash so I guess i need to dunk my head in professional code from time to time. :)

Hey, the algo makes use of heavy inlining of the original methods (actually there’s one method remaining to be inlined, so it’ll get worse) in order to save those few milliseconds that kick up the framerate a little more. What’s good is that everything is coded only once, which doesn’t bloat the source code as automated inlining would tempt one to do, so it’s kind of space-efficient also. What’s bad is that I might have exaggerated with reusing the same variables, so the code may indeed not be terribly readable.

What you can do, if you are really interested, is to compare my port to the original c++ code, that might give you some ideas and insights about basic code refactoring.

If you have any questions, don’t hesitate to drop me a line. Don’t explode that head, you’ll need it next time.

This is great, I had a quick look into the source and it’s quite complex, amazing you get that speed! I am going to try it in the future for some live face 3D triangulation. Very nice blog Hristo – subscribed :)

First of all, great to hear from all of you great thinkers here, its quite a kick actually. And no, not really, if you check out the audio demo, you’ve got some artifacts that might be due to what you have pinpointed – have you tried to simply deny the case of non-numeric Numbers as coordinates?

Please share your sources; I’ll have to put up a decent result datastructure for the solver anyway, so I’ll be working on this code again eventually.

Ha : I am actually. I’ll update the source – the intersection code is the same though. Tell me what happens.

I am curious to know if you used the double linked list or the binary tree implementation?

I actually did refer to the same double linked list reference implementation, tried to get some sample output, and I realized that it wasn’t exactly giving all the edges as required.

So I tried to do one in c\c++ with the binary tree instead since it was hard to visualize the double linked list. I won’t say that the binary tree one is working completely well either. I managed to get some of the missing edges but just that not all the end points of the edges are correct at the moment.

A double linked list. The underlying data-structure shouldn’t be influencing your output really; there’s another problem with the implementation which could yield some artefacts, Mario described it pretty well a few comments above.

Choosing between double-linked and binary tree depends on what you want to achieve – if you’re planning to render huge graphs with tens of thousands of vertices, a binary tree will probably speed things up. However, for real time stuff in flash, where you’d probably have less than a thousand vertices, a double linked list, with approximative lookup of a ‘nearest’ arc before intersection tests kick in could be cheaper than the tree reorganisation logic.

This said, I have little to no experience with binary trees, so I might be wrong.

marvellous monsieur !
delaunay/voronoi makes beautiful sense to me – check CGAL for inspiration (c++)
- but i think real time 3d modelling through AR input in flash is coming! anyone interested? I think so !
I absolutely agree with the previous post – a double linked list (plus a nice dictionary object for keeping the whole thing tidy) is the way to go ….inline code is the new oop … (only kidding!) – but yes, i think perhaps its time to get mr j. ebert into this conversation for some SERIOUS optimisations – this is a real case for pushin it to the max……lovin your work!…hope to ping pong a few files of my own to add to the conversation v soon. all power to your elbow – ancient alexandria had nothing on the new mathematical playground – we are all allowed to play now ! j

Great library! I’m really enjoying working with it. I found a small issue, and wanted to let you know about it. If there are two or more points with exactly the same x value that are the furthest point to the left, you will see a lot of strange artifacts, with overlapping surfaces. The issue appears to be in the intersection function in Fortune.as in the if statement where p0.x == p1.x. It looks like there needs to be another condition there.

Its late here, so I took the easy way out and added a new point so far to the extreme left that the issue never surfaces. I feel so lazy. ;)

Hey Matt!
Actually, I’m seeing that, except for the link, I haven’t really explicitly credited you for the code in the post – sorry for that, will fix it.
Meanwhile, have you got any clues about the math problems we’re seeing here? Is it my interpretation of your math that’s off?
Thanks!