<jupyter_start><jupyter_text>Getting Started: Tessellation of Frankfurt am Main This example shows the basic functions of `tesspy`, which are five types of tessellations: square, hexagon, adaptive squares, voronoi diagrams and city blocks. We have selected the city of **Frankfurt am Main** in Germany to demonstrate tessellation.  Import TessellationWe start by importing the `Tessellation` object from `tesspy` module:<jupyter_code>from tessellation import Tessellation
# Shapely 1.8.1 makes pandas to produce many warnings; this is to get rid of these warnings
import warnings
warnings.simplefilter("ignore")<jupyter_output><empty_output><jupyter_text>Defining the areaThere are different ways to define the area. The most straightforward way is passing an address.<jupyter_code>ffm= Tessellation('Frankfurt am Main')<jupyter_output><empty_output><jupyter_text>With `.get_polygon()` method, we can retrieve the polygon. This is in the form of a GeoPandas GeoDataFrame. We visualize the polygon to make sure data collection was successful and correct:<jupyter_code>ffm.get_polygon().plot(figsize=(10,10)).set_axis_off();<jupyter_output><empty_output><jupyter_text>The polygon shows the city of Frankfurt. Note that the `CRS` of the GeoPandas is `EPSG:4326`. We can double-check that:<jupyter_code>print(ffm.get_polygon().crs)<jupyter_output>epsg:4326<jupyter_text>It is already ready for tessellation.  SquaresThe first tessellation method is the square grid. It creates (almost) equal squares that cover the whole area surface. In order to set the size, we need to pass a `resolution`. This value is usually between 1 and 21. Larger values mean smaller squares and consequently a finer tessellation.For example, with a `resolution=13`, we have:<jupyter_code>ffm_sqr_13=ffm.squares(13)
ffm_sqr_13.plot(lw=1, edgecolor='w', figsize=(10,10)).set_axis_off();
ffm_sqr_13.head()<jupyter_output><empty_output><jupyter_text>The square grid with a `resolution=15` look like this:<jupyter_code>ffm_sqr_15=ffm.squares(15)
ffm_sqr_15.plot(lw=1, edgecolor='w',figsize=(10,10)).set_axis_off();<jupyter_output><empty_output><jupyter_text>As it can be seen the number of square are relatively higher when resolution is higher. We can check the number of squares for each resolution:<jupyter_code>print('Resolution=13  ==>  Number of squares:  ', ffm_sqr_13.shape[0])
print('Resolution=15  ==>  Number of squares:  ', ffm_sqr_15.shape[0])<jupyter_output>Resolution=13  ==>  Number of squares:   45
Resolution=15  ==>  Number of squares:   488<jupyter_text>hexagonsThe next method is hexagons. Similar to squares, this method creates (almost) equal shapes to cover the area. A slight difference is that the algorithm finds the optimal number of hexagons, and not all the surface is covered. Therefore, there may be some areas on the borders which are left behind.Similarly, we need to pass a resolution to set the hexagon sizes. The larger numbers mean smaller hexagons. A suitable value is usually between 5 and 15.Here is the hexagon tessellation with `resolution=7`:<jupyter_code>ffm_hex_7=ffm.hexagons(7)
ffm_hex_7.plot(lw=1, edgecolor='w',figsize=(10,10)).set_axis_off();
ffm_hex_7.head()<jupyter_output><empty_output><jupyter_text>At the next resolution, in this case, `resolution=8`, each hexagon is divided into 7 sub-hexagons. This means the total number of hexagons is (almost) 7 times more when resolution increments one unit. Following plot shows the hexagons of Frankfurt with `resolution=8`:<jupyter_code>ffm_hex_8=ffm.hexagons(8)
ffm_hex_8.plot(lw=1, edgecolor='w',figsize=(10,10)).set_axis_off();
print('Resolution=7  ==>  Number of hexagons:  ', ffm_hex_7.shape[0])
print('Resolution=8  ==>  Number of hexagons:  ', ffm_hex_8.shape[0])<jupyter_output>Resolution=7  ==>  Number of hexagons:   53
Resolution=8  ==>  Number of hexagons:   366<jupyter_text>Adaptive squaresAdaptive squares are an extension of regular squares. This method starts with relatively large squares and uses the spatial data, i.e., Points of Interests (POI), to divide the high-density squares into 4 subsquares. The division of squares is done until a specific threshold for POI count per square is reached.The spatial data are retrieved from OpenStreetMap (OSM). We can use which POI categories we want to use. The selected POI categories should be passed as a list. These categories are the OSM primary categories, which represent physical objects on the map. More information can be found at this [link](https://wiki.openstreetmap.org/wiki/Map_features).You can see the top-level categories by:<jupyter_code>print(Tessellation.osm_primary_features())<jupyter_output>['aerialway', 'aeroway', 'amenity', 'barrier', 'boundary', 'building', 'craft', 'emergency', 'geological', 'healthcare', 'highway', 'historic', 'landuse', 'leisure', 'man_made', 'military', 'natural', 'office', 'place', 'power', 'public_transport', 'railway', 'route', 'shop', 'sport', 'telecom', 'tourism', 'water', 'waterway']<jupyter_text>So we build the adaptive squares for<jupyter_code># Adaptive Squares using only amenity data
ffm_asq = ffm.adaptive_squares(start_resolution=13, 
                                poi_categories=["amenity"], 
                                threshold=None,
                                timeout=60,
                                verbose=True)<jupyter_output>Getting data from OSM...
Creating POI DataFrame...
Cleaning POI DataFrame...
Threshold=198  ==> set as the median POI-count per square at the initial level
Threshold exceeded! Squares are subdivided into resolution 14
Threshold exceeded! Squares are subdivided into resolution 15
Threshold exceeded! Squares are subdivided into resolution 16
Threshold exceeded! Squares are subdivided into resolution 17<jupyter_text>We visualize the adaptive squares:<jupyter_code>ffm_asq.plot(lw=1, edgecolor='w', figsize=(10,10)).set_axis_off();
ffm_asq.head()<jupyter_output><empty_output><jupyter_text>Voronoi-DiagramsVoronoi-Diagram is a method for tessellation that uses irregular shapes to cover the area. In this method, we have a given set of points, called generators. For each generator, there is a polygon that contains the area that is closer to this generator than other generators.In this context, the generators are the POI, coming from OSM as explained for adaptive squares. Usually, the number of POI is larger than the required number of polygons. So, we can use a clustering method to cluster POI in the first step and then use the cluster centroids as the generator points.In the example below, we use `shop` and `public_transport` as POI. We use the `k-means` clustering algorithm to cluster the POI and build the generators. The number of polygons is set to 100.<jupyter_code>ffm_voronoi= ffm.voronoi(cluster_algo='k-means',
                        poi_categories=['shop','public_transport'],
                        timeout=60,
                        n_polygons=100,
                        verbose=True)<jupyter_output>Getting data from OSM...
Creating POI DataFrame...
Cleaning POI DataFrame...
K-Means Clustering...
Creating Voronoi polygons...<jupyter_text>We can now plot and visualize the voronoi polygons:<jupyter_code>ffm_voronoi.plot(lw=1, edgecolor='w', figsize=(10,10)).set_axis_off();
ffm_voronoi.head()
print('Number of polygons ==> ' ,len(ffm_voronoi))<jupyter_output>Number of polygons ==>  100<jupyter_text>City blocksThe last tessellation method is city blocks. We define city blocks as the smallest area surrounded by street segments. This method gets the road network data from OSM and generates polygons based on the roads. We use hierarchical clustering to merge a group of contiguous polygons. This guarantees that tiny polygons like road islands are not identified as single polygons. The number of desired polygons can be passed. This would be an approximation. The final number of city blocks could slightly vary.For example, the following is the example of city blocks for Frankfurt:<jupyter_code>ffm_cb = ffm.city_blocks(n_polygons=500,
                          detail_deg=None,
                          split_roads=True,
                          verbose=True)
ffm_cb.plot(lw=1, edgecolor='w', figsize=(10,10)).set_axis_off();
ffm_cb.head()
print('Number of polygons ==> ' ,len(ffm_cb))<jupyter_output>Number of polygons ==>  760
StarcoderdataJupyterStructuredCleanDedup