.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "_auto_examples/plot_create_zoning.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr__auto_examples_plot_create_zoning.py: Creating a zone system based on Hex Bins ======================================== On this example we show how to create a hex bin zones covering an arbitrary area. We use the Nauru example to create roughly 100 zones covering the whole modelling area as delimited by the entire network You are obviously welcome to create whatever zone system you would like, as long as you have the geometries for them. In that case, you can just skip the Hex bin computation part of this notebook. We also add centroid connectors to our network to make it a pretty complete example .. GENERATED FROM PYTHON SOURCE LINES 18-19 **What we want to create a zoning system like this** .. GENERATED FROM PYTHON SOURCE LINES 21-27 .. code-block:: python from PIL import Image import matplotlib.pyplot as plt img = Image.open("plot_create_zoning.png") plt.imshow(img) .. image-sg:: /_auto_examples/images/sphx_glr_plot_create_zoning_001.png :alt: plot create zoning :srcset: /_auto_examples/images/sphx_glr_plot_create_zoning_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out Out: .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 28-29 # Imports .. GENERATED FROM PYTHON SOURCE LINES 29-37 .. code-block:: python from uuid import uuid4 from tempfile import gettempdir from os.path import join from math import sqrt from shapely.geometry import Point import shapely.wkb from aequilibrae.utils.create_example import create_example .. GENERATED FROM PYTHON SOURCE LINES 38-39 We create an empty project on an arbitrary folder .. GENERATED FROM PYTHON SOURCE LINES 39-44 .. code-block:: python fldr = join(gettempdir(), uuid4().hex) # Let's use the Nauru example project for display project = create_example(fldr, "nauru") .. GENERATED FROM PYTHON SOURCE LINES 45-46 We said we wanted 100 zones .. GENERATED FROM PYTHON SOURCE LINES 46-48 .. code-block:: python zones = 100 .. GENERATED FROM PYTHON SOURCE LINES 49-50 Hex Bins using SpatiaLite .. GENERATED FROM PYTHON SOURCE LINES 53-54 ### Spatialite requires a few things to compute hex bins .. GENERATED FROM PYTHON SOURCE LINES 56-57 One of the them is the area you want to cover .. GENERATED FROM PYTHON SOURCE LINES 57-62 .. code-block:: python network = project.network # So we use the convenient network method convex_hull() (it may take some time for very large networks) geo = network.convex_hull() .. GENERATED FROM PYTHON SOURCE LINES 63-65 The second thing is the side of the hexbin, which we can compute from its area The approximate area of the desired hexbin is .. GENERATED FROM PYTHON SOURCE LINES 65-70 .. code-block:: python zone_area = geo.area / zones # Since the area of the hexagon is **3 * sqrt(3) * side^2 / 2** # is side is equal to **sqrt(2 * sqrt(3) * A/9)** zone_side = sqrt(2 * sqrt(3) * zone_area / 9) .. GENERATED FROM PYTHON SOURCE LINES 71-75 Now we can run an sql query to compute the hexagonal grid There are many ways to create Hex bins (including with a GUI on QGIS), but we find that using SpatiaLite is a pretty neat solution For which we will use the entire network bounding box to make sure we cover everything .. GENERATED FROM PYTHON SOURCE LINES 75-86 .. code-block:: python extent = network.extent() curr = project.conn.cursor() b = extent.bounds curr.execute( "select st_asbinary(HexagonalGrid(GeomFromWKB(?), ?, 0, GeomFromWKB(?)))", [extent.wkb, zone_side, Point(b[2], b[3]).wkb], ) grid = curr.fetchone()[0] grid = shapely.wkb.loads(grid) .. GENERATED FROM PYTHON SOURCE LINES 87-89 Since we used the bounding box, we have WAY more zones than we wanted, so we clean them by only keeping those that intersect the network convex hull. .. GENERATED FROM PYTHON SOURCE LINES 89-98 .. code-block:: python grid = [p for p in grid if p.intersects(geo)] # Let's re-number all nodes with IDs smaller than 300 to something bigger as to free space to our centroids to go from 1 # to N nodes = network.nodes for i in range(1, 301): nd = nodes.get(i) nd.renumber(i + 1300) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none /home/runner/work/aequilibrae/aequilibrae/docs/source/examples/plot_create_zoning.py:89: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the `geoms` property to access the constituent parts of a multi-part geometry. grid = [p for p in grid if p.intersects(geo)] .. GENERATED FROM PYTHON SOURCE LINES 99-101 Now we can add them to the model And add centroids to them while we are at it .. GENERATED FROM PYTHON SOURCE LINES 101-111 .. code-block:: python zoning = project.zoning for i, zone_geo in enumerate(grid): zone = zoning.new(i + 1) zone.geometry = zone_geo zone.save() # None means that the centroid will be added in the geometric point of the zone # But we could provide a Shapely point as an alternative zone.add_centroid(None) .. GENERATED FROM PYTHON SOURCE LINES 112-113 # Centroid connectors .. GENERATED FROM PYTHON SOURCE LINES 115-127 .. code-block:: python for zone_id, zone in zoning.all_zones().items(): # We will connect for walk, with 1 connector per zone zone.connect_mode(mode_id="w", connectors=1) # And for cars, for cars with 2 connectors per zone # We also specify the link types we accept to connect to (can be used to avoid connection to ramps or freeways) zone.connect_mode(mode_id="c", link_types="ytrusP", connectors=2) # This takes a few minutes to compute, so we will break after processing the first 10 zones if zone_id >= 10: break .. rst-class:: sphx-glr-script-out Out: .. code-block:: none /home/runner/work/aequilibrae/aequilibrae/aequilibrae/project/network/connector_creation.py:75: UserWarning: We have fewer possible nodes than required connectors for zone 1. Will connect all of them. warn(f"We have fewer possible nodes than required connectors for zone {zone_id}. Will connect all of them.") .. GENERATED FROM PYTHON SOURCE LINES 128-130 Let's add an special generator zones We also add a centroid at the airport terminal .. GENERATED FROM PYTHON SOURCE LINES 130-144 .. code-block:: python nodes = project.network.nodes # Let's use some silly number for its ID, like 10,000, just so we can easily differentiate it airport = nodes.new_centroid(10000) airport.geometry = Point(166.91749582, -0.54472590) airport.save() # When connecting a centroid not associated with a zone, we need to tell AequilibraE what is the initial area around # the centroid that needs to be considered when looking for candidate nodes # Distance here is in degrees, so 0.01 is equivalent to roughly 1.1km airport.connect_mode(airport.geometry.buffer(0.01), mode_id="c", link_types="ytrusP", connectors=1) .. GENERATED FROM PYTHON SOURCE LINES 148-149 .. code-block:: python project.close() .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 36.039 seconds) .. _sphx_glr_download__auto_examples_plot_create_zoning.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_create_zoning.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_create_zoning.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_