fataneh farahani
fataneh farahani

Reputation: 21

Hexagonal lattice in different layers by networkx

How can I expand this code, to include a different number of hexagonal layers? I need a graph of a hexagonal lattice given number m of layers. m=1 means 1 regular hexagon with side 1 and center at the origin, for m=2 add 6 regular hexagons around the initial one, for m=3 add the 3rd layer of hexagons, so on.

import networkx as nx
import matplotlib.pyplot as plt
G = nx.hexagonal_lattice_graph(m=2,n=3, periodic=False, with_positions=True, 
                               create_using=None)
pos = nx.get_node_attributes(G, 'pos')
nx.draw(G, pos=pos, with_labels=True)
plt.show()

Upvotes: 2

Views: 1003

Answers (1)

Ram Narasimhan
Ram Narasimhan

Reputation: 22506

An interesting question! Took me a little longer than I expected. Basically, the function hexagonal_lattice_graph() produces a m x n rectangular grid of hexagons. So, the task is to first draw a large grid, and then remove the nodes that are outside of the outermost layer. I use distance to decide which nodes remain, and which ones get removed. It was further tricky because odd and even m behave slightly differently. So the center coordinates have to be calculated carefully.

import networkx as nx
import matplotlib.pyplot as plt


def node_dist(x,y, cx, cy):
    """Distance of each node from the center of the innermost layer"""
    return abs(cx-x) + abs(cy-y)


def remove_unwanted_nodes(G, m):
    """Remove all the nodes that don't belong to an m-layer hexagonal ring."""
    
    #Compute center of all the hexagonal rings as cx, cy
    cx, cy = m-0.5, 2*m -(m%2) #odd is 2m-1, even is 2m
    
    #in essence, we are converting from a rectangular grid to a hexagonal ring... based on distance.
    unwanted = []
    for n in G.nodes:    
        x,y = n
        #keep short distance nodes, add far away nodes to the list called unwanted
        if node_dist(x,y, cx, cy) > 2*m:
            unwanted.append(n)

    #now we are removing the nodes from the Graph
    for n in unwanted:
        G.remove_node(n)
        
    return G



##################
m = 4 #change m here. 1 = 1 layer, single hexagon.
G = nx.hexagonal_lattice_graph(2*m-1,2*m-1, periodic=False, 
                               with_positions=True, 
                               create_using=None)
pos = nx.get_node_attributes(G, 'pos')
G = remove_unwanted_nodes(G, m)

#render the result
plt.figure(figsize=(9,9)) 
nx.draw(G, pos=pos, with_labels=True)
plt.axis('scaled')
plt.show()

Which produces the following for m=3: Hex Ring for m =3

and for m=4:

Hexagonal Ring for m=4

Welcome to SO! Hope the solution above is clear and helps you move forward.

Upvotes: 3

Related Questions