tessellation module¶
Module for setting up hexagon network.
- grabs the spatial bounds of fire shapefile.
- using user-defined area value to build hexagon network on the bounded area.
- projection of the hexagon network to be the same as that of the fire shapefile.
- generate the centroid of the hexes as nodes shapefile
- generate arcs connecting neighbouring nodes
create_arcs(hexagons, **kwargs)
¶
Create geometry of arcs connecting each neighbouring hexagons.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
hexagons |
GeoDataFrame |
geometry and ID of hexagonal patches |
required |
Returns:
Type | Description |
---|---|
GeoDataFrame |
return arcs geometry with attributes indicating IDs of the two hexagons it connects. |
Source code in postbp/tessellation.py
def create_arcs(hexagons, **kwargs):
"""Create geometry of arcs connecting each neighbouring hexagons.
Args:
hexagons (GeoDataFrame): geometry and ID of hexagonal patches
Returns:
GeoDataFrame: return arcs geometry with attributes indicating IDs of the two hexagons it connects.
"""
hexagon = hexagons.copy()
if 'Node_ID' in kwargs:
hexagon = hexagon.rename(columns={kwargs["Node_ID"]: 'Node_ID'})
nodes = nodes_from_hexagons(hexagon)
nodes = nodes.set_index('Node_ID')
SRID = hexagon.crs
hexagon = hexagon.set_index('Node_ID')
arcs = gpd.GeoDataFrame()
df=gpd.GeoDataFrame()
for index, _ in tqdm(hexagon.iterrows()):
nnnn = hexagon[~hexagon.geometry.disjoint(hexagon.at[index,'geometry'])].index.tolist()
nnnn = [i for i in nnnn if index != i]
mmmm = [index] * len(nnnn)
mmnn = [LineString(xy) for xy in zip(nodes.loc[mmmm].geometry, nodes.loc[nnnn].geometry)]
mmnn = gpd.GeoDataFrame(df, crs = SRID, geometry = mmnn )
mmnn['Node_1'] = mmmm
mmnn['Node_2'] = nnnn
arcs = pd.concat([arcs,mmnn])
arcs['Node_1'] = arcs['Node_1'].astype(int)
arcs['Node_2'] = arcs['Node_2'].astype(int)
arcs.reset_index(drop=True, inplace=True)
return arcs
create_hexagons(boundaryShp, offset_x=0, offset_y=0, **kwargs)
¶
Creat geodataframe of hexagonal patches of defined size and range. Hexagon size can be defined in area, side length, or long diameter. Must input one parameter out of the three options.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
boundaryShp |
GeoDataFrame |
the geodataframe defines the range covered by the hexagonal patches |
required |
area |
float, OPTIONAL |
define the size of each hexagon by area in square meters |
required |
side |
float, OPTIONAL |
define the size of each hexagon by side length in meter |
required |
diameter |
float, OPTIONAL |
define the size of each hexagon by long diameter in meter |
required |
offset_x |
fraction, OPTIONAL |
defines the horizontal offset for hexagons as a fraction of the length of the hexagon's long diagonal. Can be positive or negative. |
0 |
offset_y |
fraction, OPTIONAL |
defines the vertical offset for hexagons as a fraction of the length of the hexagon's long diagonal. Can be positive or negative. |
0 |
Returns:
Type | Description |
---|---|
GeoDataFrame |
return a geodataframe of hexagonal network of the defined size and covering the defined range. |
Source code in postbp/tessellation.py
def create_hexagons(boundaryShp, offset_x=0, offset_y=0, **kwargs):
"""Creat geodataframe of hexagonal patches of defined size and range.
Hexagon size can be defined in area, side length, or long diameter. Must input one parameter out of the three options.
Args:
boundaryShp (GeoDataFrame): the geodataframe defines the range covered by the hexagonal patches
area (float, OPTIONAL): define the size of each hexagon by area in square meters
side (float, OPTIONAL): define the size of each hexagon by side length in meter
diameter (float, OPTIONAL): define the size of each hexagon by long diameter in meter
offset_x (fraction, OPTIONAL): defines the horizontal offset for hexagons as a fraction of the length of the hexagon's long diagonal. Can be positive or negative.
offset_y (fraction, OPTIONAL): defines the vertical offset for hexagons as a fraction of the length of the hexagon's long diagonal. Can be positive or negative.
Returns:
GeoDataFrame: return a geodataframe of hexagonal network of the defined size and covering the defined range.
"""
if 'area' in kwargs:
area = kwargs['area']
elif "side" in kwargs:
area = kwargs["side"]**2*3/2*math.sqrt(3)
elif "diameter" in kwargs:
area = kwargs["diameter"]**2*3/8*math.sqrt(3)
else:
print('Please define a value using one of the following parameters: area, side, or diameter of the intended hexagonal patches.')
myCRS = boundaryShp.crs
xmin,ymin,xmax,ymax = boundaryShp.total_bounds
nodes = _create_hexnodes(area, xmin, ymin, xmax, ymax, offset_x, offset_y)
hexagons = [_create_hexgrids(area, node[0], node[1]) for node in nodes]
nodes = [Point(node) for node in nodes]
nodes = gpd.GeoDataFrame({'geometry': nodes})
nodes['Node_ID'] = nodes.index + 1
nodes.crs = myCRS
hexagons = gpd.GeoDataFrame({'geometry':hexagons})
hexagons['Node_ID'] = hexagons.index + 1
hexagons.crs = myCRS
return hexagons
create_hexagons_nodes(boundaryShp, offset_x=0, offset_y=0, **kwargs)
¶
Creat geodataframe of hexagonal patches and the nodes (centroids) of the hexagons of defined size and range. Hexagon size can be defined in area, side length, or long diameter. Must input one parameter out of the three options.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
boundaryShp |
GeoDataFrame |
the geodataframe defines the range covered by the hexagonal patches |
required |
area |
float, OPTIONAL |
define the size of each hexagon by area in square meters |
required |
side |
float, OPTIONAL |
define the size of each hexagon by side length in meter |
required |
diameter |
float, OPTIONAL |
define the size of each hexagon by long diameter in meter |
required |
offset_x |
fraction, OPTIONAL |
defines the horizontal offset for hexagons as a fraction of the length of the hexagon's long diagonal. Can be positive or negative. |
0 |
offset_y |
fraction, OPTIONAL |
defines the vertical offset for hexagons as a fraction of the length of the hexagon's long diagonal. Can be positive or negative. |
0 |
Returns:
Type | Description |
---|---|
GeoDataFrame |
return geodataframes of hexagons and nodes of the defined size and covering the defined range. Note to give two variable names when using this function. |
Source code in postbp/tessellation.py
def create_hexagons_nodes(boundaryShp, offset_x=0, offset_y=0, **kwargs):
"""Creat geodataframe of hexagonal patches and the nodes (centroids) of the hexagons of defined size and range.
Hexagon size can be defined in area, side length, or long diameter. Must input one parameter out of the three options.
Args:
boundaryShp (GeoDataFrame): the geodataframe defines the range covered by the hexagonal patches
area (float, OPTIONAL): define the size of each hexagon by area in square meters
side (float, OPTIONAL): define the size of each hexagon by side length in meter
diameter (float, OPTIONAL): define the size of each hexagon by long diameter in meter
offset_x (fraction, OPTIONAL): defines the horizontal offset for hexagons as a fraction of the length of the hexagon's long diagonal. Can be positive or negative.
offset_y (fraction, OPTIONAL): defines the vertical offset for hexagons as a fraction of the length of the hexagon's long diagonal. Can be positive or negative.
Returns:
GeoDataFrame: return geodataframes of hexagons and nodes of the defined size and covering the defined range.
Note to give two variable names when using this function.
"""
if 'area' in kwargs:
area = kwargs['area']
elif "side" in kwargs:
area = kwargs["side"]**2*3/2*math.sqrt(3)
elif "diameter" in kwargs:
area = kwargs["diameter"]**2*3/8*math.sqrt(3)
else:
print('Please define a value using one of the following parameters: area, side, or diameter of the intended hexagonal patches.')
myCRS = boundaryShp.crs
xmin,ymin,xmax,ymax = boundaryShp.total_bounds
nodes = _create_hexnodes(area, xmin, ymin, xmax, ymax, offset_x, offset_y)
hexagons = [_create_hexgrids(area, node[0], node[1]) for node in nodes]
nodes = [Point(node) for node in nodes]
nodes = gpd.GeoDataFrame({'geometry': nodes})
nodes['Node_ID'] = nodes.index + 1
nodes.crs = myCRS
hexagons = gpd.GeoDataFrame({'geometry':hexagons})
hexagons['Node_ID'] = hexagons.index + 1
hexagons.crs = myCRS
return hexagons, nodes
nodes_from_hexagons(hexagons)
¶
Generate nodes geometry from hexagons
Parameters:
Name | Type | Description | Default |
---|---|---|---|
hexagons |
GeoDataFrame |
geometry and ID of hexagonal patches |
required |
Returns:
Type | Description |
---|---|
GeoDataFrame |
return nodes geometry with ID attributes same as the hexagons. |
Source code in postbp/tessellation.py
def nodes_from_hexagons(hexagons):
"""Generate nodes geometry from hexagons
Args:
hexagons (GeoDataFrame): geometry and ID of hexagonal patches
Returns:
GeoDataFrame: return nodes geometry with ID attributes same as the hexagons.
"""
nodes = hexagons.copy()
nodes['centroid'] = nodes.geometry.centroid
nodes.drop(labels='geometry', axis=1, inplace=True)
nodes.rename(columns={'centroid':'geometry'}, inplace=True)
nodes = nodes.set_geometry('geometry')
return nodes