I'm implementing Voronoi tesselation followed by smoothing. For the smoothing I was going to do Lloyd relaxation, but I've encountered a problem.
I'm using following module for calculation of Voronoi sides:
https://bitbucket.org/mozman/geoalg/src/5bbd46fa2270/geoalg/voronoi.py
For the smoothing I need to know the edges of each polygon so I can calculate the centre, which unfortunately this code doesn't provide.
Information I have access to consists of:
- A list of all nodes,
- A list of all edges (but just where they are, not what nodes they're associated with).
Can anyone see a relatively simple way to calculate this?
Maybe this can help you: https://github.com/Bennyelg/geo_polygon_finder This repository receive a list of cities and translate them into polygons.
For finding a centroid, you can use the formula described on wikipedia:
I used a gift-wrapping algorithm to find the outside points (a.k.a. convex hull). There are a bunch of ways to do this, but gift-wrapping is nice because of its conceptual and practical simplicity. Here's an animated gif explaining this particular implementation:
Here's some naive code to find centroids of the individual voronoi cells based on a collection of nodes and edges for a voronoi diagram. It introduces a method to find edges belonging to a node and relies on the previous centroid and convex-hull code:
Below is an image of the script results. The blue lines are edges. The black squares are nodes. The red squares are vertices that the blue lines are derived from. The vertices and nodes were chosen arbitrarily. The red crosses are centroids. While not an actual voronoi tesselation, the method used to procure the centroids should hold for tessalations composed of convex cells:
Here's the html to render the image:
This will likely get the job done. A more robust algo for finding which edges belong to a cell would be to use an inverse gift-wrapping method where edges are linked end-to-end and path choice at a split would be determined by angle. That method would not have a susceptibility to concave polygons and it would have the added benefit of not relying on the nodes.
This is @mgamba's answer, rewritten in a bit more of a python style. In particular, it uses
itertools.cycle
on the points so that "one-plus-the-last-point" can be treated as the first point in a more natural way.