|
| 1 | +.. include:: ../../include/global.rst |
| 2 | + |
| 3 | +.. _tutorials-delaunay-triangulation: |
| 4 | + |
| 5 | +====================== |
| 6 | +Delaunay Triangulation |
| 7 | +====================== |
| 8 | + |
| 9 | +.. _GRG: https://igraph.org/python/doc/api/igraph.Graph.html#GRG |
| 10 | +.. |GRG| replace:: :meth:`GRG` |
| 11 | + |
| 12 | +This example demonstrates how to calculate the `Delaunay triangulation <https://en.wikipedia.org/wiki/Delaunay_triangulation>`_ of an input graph. We start by generating a set of points on a 2D grid using |GRG|_ with radius zero, so that there are initially no edges in the graph. |
| 13 | + |
| 14 | +.. code-block:: python |
| 15 | +
|
| 16 | + import igraph as ig |
| 17 | + import matplotlib.pyplot as plt |
| 18 | + import random |
| 19 | + from scipy.spatial import Delaunay |
| 20 | +
|
| 21 | + # Generate a random geometric graph |
| 22 | + random.seed(0) |
| 23 | + g = ig.Graph.GRG(30, 0) |
| 24 | +
|
| 25 | +We then use `SciPy's Delaunay function <https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.Delaunay.html>`_ to generate the triangles, and then loop through them to add them back into our original graph. We make sure to simplify the graph afterwards to remove multiple edges caused by triangles sharing a side. |
| 26 | + |
| 27 | +.. code-block:: python |
| 28 | +
|
| 29 | + # Calculate the delaunay triangulation, and add the edges into the original graph |
| 30 | + coords = g.layout_auto().coords |
| 31 | + delaunay = Delaunay(coords) |
| 32 | + for tri in delaunay.simplices: |
| 33 | + g.add_edges([ |
| 34 | + (tri[0], tri[1]), |
| 35 | + (tri[1], tri[2]), |
| 36 | + (tri[0], tri[2]), |
| 37 | + ]) |
| 38 | + g.simplify() |
| 39 | +
|
| 40 | +Finally, we display the graph: |
| 41 | + |
| 42 | +.. code-block:: python |
| 43 | +
|
| 44 | + # Plot the graph |
| 45 | + fig, ax = plt.subplots() |
| 46 | + ig.plot( |
| 47 | + g, |
| 48 | + target=ax, |
| 49 | + vertex_size=0.04, |
| 50 | + vertex_color="lightblue", |
| 51 | + edge_width=0.8 |
| 52 | + ) |
| 53 | + plt.show() |
| 54 | +
|
| 55 | +Our output looks like this: |
| 56 | + |
| 57 | +.. figure:: ./figures/delaunay-triangulation.png |
| 58 | + :alt: The visual representation of a Delaunay triangulation |
| 59 | + :align: center |
| 60 | + |
| 61 | + The Delaunay triangulation |
| 62 | + |
| 63 | +Advanced: Improving plotting style |
| 64 | +---------------------------------- |
| 65 | +Sometimes, we would like to emphasise the actual triangles generated by the Delaunay triangulation. We'll add in some triangles and color them according to their y coordinate. |
| 66 | + |
| 67 | +.. code-block:: python |
| 68 | +
|
| 69 | + # Plot the triangles |
| 70 | + fig, ax = plt.subplots() |
| 71 | +
|
| 72 | + palette = ig.GradientPalette("midnightblue", "lightblue", 100) |
| 73 | + for tri in delaunay.simplices: |
| 74 | + # get the points of the triangle |
| 75 | + tri_points = [delaunay.points[tri[i]] for i in range(3)] |
| 76 | +
|
| 77 | + # calculate the vertical center of the triangle |
| 78 | + center = (tri_points[0][1] + tri_points[1][1] + tri_points[2][1]) / 3 |
| 79 | +
|
| 80 | + # draw triangle onto axes |
| 81 | + poly = plt.Polygon(tri_points, color=palette.get(int(center*100))) |
| 82 | + ax.add_patch(poly) |
| 83 | +
|
| 84 | +We then plot the original graph edges on top: |
| 85 | + |
| 86 | +.. code-block:: python |
| 87 | +
|
| 88 | + # Plot the graph on top |
| 89 | + ig.plot( |
| 90 | + g, |
| 91 | + target=ax, |
| 92 | + vertex_size=0.0, |
| 93 | + edge_width=0.2, |
| 94 | + edge_color="white", |
| 95 | + ) |
| 96 | + plt.show() |
| 97 | +
|
| 98 | +The final output looks like this: |
| 99 | + |
| 100 | +.. figure:: ./figures/delaunay-triangulation2.png |
| 101 | + :alt: The visual representation of a Delaunay triangulation |
| 102 | + :align: center |
| 103 | + |
| 104 | + The Delaunay triangulation, with colored triangles. |
0 commit comments