Skip to content

Instantly share code, notes, and snippets.

@timlinux
Last active October 11, 2022 15:37
Show Gist options
  • Save timlinux/352ee1c1b7e753255f1208df3cf8bbdd to your computer and use it in GitHub Desktop.
Save timlinux/352ee1c1b7e753255f1208df3cf8bbdd to your computer and use it in GitHub Desktop.

H3 Playground

In this example I show how we can use the H3 API to do a simple workflow whereby we create a series of hex indexes along the boundary of a polygon and then calculate the distance of a point to all of the polygon boundary indices.

First we need to import h3 and pandas which will provide all the data structures and processing capabilities we need:

import h3
import pandas

Now we set two variables:

  • The zoom level that the H3 indexes should be taken from
  • A polygon boundary for the breede river district in South Africa
zoom_level = 12
breede = {
 "type": "Polygon", 
    "coordinates": [ [ 
        [ 19.413943058300504, -33.690263063631619 ], 
        [ 19.414477991361053, -33.690227021447981 ], 
        [ 19.414438931692246, -33.689170063457794 ], 
        [ 19.414936984378812, -33.688270014695007 ], 
        [ 19.416262917641831, -33.687189000642718 ], 
        [ 19.417801918883526, -33.686549042335429 ], 
        [ 19.419035986487756, -33.686122068187757 ], 
        [ 19.420098476534037, -33.685790983012424 ], 
        [ 19.42046585535013, -33.685977731815115 ], 
        [ 19.420627793719461, -33.685591661354948 ], 
        [ 19.420806244438012, -33.685239034688436 ], 
        [ 19.420883022671092, -33.685087322241003 ], 
        [ 19.421172449787662, -33.684596226534069 ], 
        [ 19.421499595468532, -33.684041260724939 ], 
        [ 19.422032181596165, -33.683136266639309 ], 
        [ 19.42340346095537, -33.680821771716012 ], 
        [ 19.423931269398196, -33.679928260837698 ], 
        [ 19.42426788662965, -33.679296600614549 ], 
        [ 19.42443409976957, -33.678947578166401 ], 
        [ 19.424567036753899, -33.678602662850807 ], 
        [ 19.424679270437395, -33.678270152751907 ], 
        [ 19.42471665372554, -33.678133024815992 ], 
        [ 19.424784044227067, -33.677888105605263 ], 
        [ 19.424841376444789, -33.677680066768517 ], 
        [ 19.425115632316619, -33.676562172342244 ], 
        [ 19.425364993936029, -33.675556427780464 ], 
        [ 19.425984165123452, -33.673071361127569 ], 
        [ 19.426752953282517, -33.670008613707978 ], 
        [ 19.426894272170045, -33.669447612928565 ], 
        [ 19.426942132837155, -33.66925382332721 ], 
        [ 19.426989825866201, -33.66906112337324 ], 
        [ 19.427071381784089, -33.669073109494775 ], 
        [ 19.427454350940081, -33.66912960352218 ], 
        [ 19.429079434327377, -33.669394220205362 ], 
        [ 19.429167695767774, -33.669524223523581 ], 
        [ 19.429659797303088, -33.669180733131526 ], 
        [ 19.429645883343824, -33.669292128624704 ], 
        [ 19.429678321309126, -33.66947326155227 ], 
        [ 19.430769477464253, -33.668883510845006 ], 
        [ 19.43381981966715, -33.667230683358213 ], 
        [ 19.433963820763665, -33.667439560385304 ], 
        [ 19.434706625022898, -33.667035636471354 ], 
        [ 19.438839992934874, -33.664780066327381 ], 
        [ 19.438878717327526, -33.664835470707345 ], 
        [ 19.439236121678846, -33.664599352494946 ], 
        [ 19.440985257233081, -33.667210147695442 ], 
        [ 19.441022891978349, -33.667251638116142 ], 
        [ 19.441333692948007, -33.667595463784323 ], 
        [ 19.44171423135208, -33.668016402961683 ], 
        [ 19.442001479173854, -33.668270458446898 ], 
        [ 19.442321751694095, -33.668546642156457 ], 
        [ 19.442586871291496, -33.66877856941727 ], [ 19.443161199296924, -33.669136728139875 ], [ 19.443868129010582, -33.669518607648456 ], [ 19.444762897174371, -33.669894200729658 ], [ 19.446872538384099, -33.670700539814959 ], [ 19.450053722095561, -33.671805023196129 ], [ 19.448206685912226, -33.674534254688439 ], [ 19.447434964087051, -33.676994007993756 ], [ 19.450700469744419, -33.680844402854575 ], [ 19.452771973294716, -33.68323265852581 ], [ 19.454185329807842, -33.684816670587537 ], [ 19.454526557086041, -33.685523432663132 ], [ 19.455062663613006, -33.686254502257924 ], [ 19.45535519203375, -33.686546946859636 ], [ 19.456061870290313, -33.68586457612227 ], [ 19.456689591019, -33.685165860673749 ], [ 19.457311863510597, -33.684543504363091 ], [ 19.457830451859934, -33.683995244076527 ], [ 19.458719436510506, -33.683165519481378 ], [ 19.458823120652767, -33.68303216340189 ], [ 19.459697353153757, -33.68371377976797 ], [ 19.460408641457065, -33.684232368117307 ], [ 19.460690189584682, -33.68429162817273 ], [ 19.461030997767722, -33.684202779999111 ], [ 19.461445818155767, -33.684187860211438 ], [ 19.462216366514497, -33.68429162817273 ], [ 19.463357227355459, -33.684336052259567 ], [ 19.465076020420213, -33.684232368117307 ], [ 19.466972677470324, -33.684143436124629 ], [ 19.467239389629299, -33.683891559934267 ], [ 19.470727434815927, -33.685084556212956 ], [ 19.47046793109368, -33.685969014635816 ], [ 19.470282942490627, -33.686600004306712 ], [ 19.467810951606708, -33.691662003271261 ], [ 19.467081977487709, -33.693154065855197 ], [ 19.466663971976431, -33.694046067990911 ], [ 19.466162985623754, -33.695037060403109 ], [ 19.465905996472458, -33.695565036484027 ], [ 19.463880928665731, -33.699710055241383 ], [ 19.463355970069983, -33.700780005181485 ], [ 19.455147991387321, -33.698647062280912 ], [ 19.455030141828701, -33.698613534668226 ], [ 19.45487951902868, -33.698901117766098 ], [ 19.454713473526795, -33.69923320876984 ], [ 19.454235956502998, -33.699482402751187 ], [ 19.453509245497855, -33.699607041651376 ], [ 19.452658063230587, -33.699710809612668 ], [ 19.451952139345309, -33.699939132655118 ], [ 19.451536983681137, -33.700333668837487 ], [ 19.451200953182905, -33.700982009047976 ], [ 19.451165916827648, -33.701073036516419 ], [ 19.451069944036306, -33.701323068688112 ], [ 19.450979922396215, -33.701668067822709 ], [ 19.450967936274679, -33.701712072814388 ], [ 19.450967936274679, -33.7021130630622 ], [ 19.449808886703863, -33.702325460488623 ], [ 19.449619623330193, -33.700995000997892 ], [ 19.448749581780788, -33.698674638742375 ], [ 19.447734365668396, -33.697224318036263 ], [ 19.445268828849919, -33.696281773024396 ], [ 19.442875963131939, -33.695556570761823 ], [ 19.44055551705739, -33.695701577686719 ], [ 19.438452665189203, -33.695846668430647 ], [ 19.436204638758085, -33.695701577686719 ], [ 19.434101870708929, -33.695484067299361 ], [ 19.431708837352886, -33.694396347724535 ], [ 19.43062111777806, -33.693598725818532 ], [ 19.429098377428545, -33.69309111776235 ], [ 19.428228252060109, -33.692583509706168 ], [ 19.42685043481643, -33.693018530480884 ], [ 19.424965177154661, -33.693163621224812 ], [ 19.421194494193003, -33.693163621224812 ], [ 19.418728957374526, -33.693018530480884 ], [ 19.416771028612231, -33.692365915499778 ], [ 19.415393379006616, -33.691423370487911 ], 
        [ 19.413943058300504, -33.690263063631619 ] ] ]
    
}

Next we fill the polygon wht Hex indices at the given zoom level:

hexes = h3.polyfill(breede, zoom_level, geo_json_conformant=True)

And then convert the list of indices to a pandas dataframe.

df = pandas.DataFrame(hexes)
df.sort_values(by=[0], inplace=True)
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
</style>
0
8232 8cbc6b2800801ff
9101 8cbc6b2800803ff
27700 8cbc6b2800805ff
17144 8cbc6b2800807ff
15034 8cbc6b2800809ff
... ...
10468 8cbc6b29d9a69ff
34051 8cbc6b29d9a6bff
21212 8cbc6b29d9a6dff
3265 8cbc6b29dd249ff
13653 8cbc6b29dd24dff

35645 rows × 1 columns

Now we so some work to find the number of neighbours our indices each have. Any index that has less than 7 neighbours can be considered an edge index so we will keep it in our edge set:

%time edge_hexes = []
for index in hexes: 
    neighbours = h3.k_ring(index,1)
    count = len(list(filter(hexes.__contains__, neighbours)))
    # If we get 7 it is the central hex + its 6 neighbours
    # to find the edge hexes we include only the ones less than 7
    #print (index, count)
    if count < 7:
        edge_hexes.append(index)
        
df_edges = pandas.DataFrame(edge_hexes, columns=['h3_index'])

Next we calculate the centroids of all edge indices and add them to our dataframe, then make a little plot of the result.

df_edges['lat'] = df_edges['h3_index'].apply(lambda row: h3.h3_to_geo(row)[0])
df_edges['lng'] = df_edges['h3_index'].apply(lambda row: h3.h3_to_geo(row)[1])  
df_edges.plot(kind='hexbin', x='lat', y='lng', figsize=(17,15))
CPU times: user 2.84 ms, sys: 0 ns, total: 2.84 ms
Wall time: 2.73 ms

output_5_2

Now we get the location of a cell somewhere outside the polygon and calculate the distance to any point on the edge.

# Example origin location
index = "87bc4ed9affffff"
location = h3.h3_to_geo(index)

Now we compute the distance from our location to the each edge cell.

df_edges['distance'] = df_edges['h3_index'].apply(
    lambda h3_index: h3.point_dist(h3.h3_to_geo(h3_index), location, unit='km'))
df_edges.sort_values(by=['distance'], inplace=True)

The results are sorted by disance as we cam see in the table below:

print(df_edges)
            h3_index        lat        lng    distance
532  8cbc6b282ca51ff -33.685098  19.470601  264.585027
234  8cbc6b282ca59ff -33.685260  19.470622  264.592333
799  8cbc6b282ca53ff -33.685023  19.470415  264.595815
916  8cbc6b282c125ff -33.684948  19.470229  264.606604
1    8cbc6b282c165ff -33.685346  19.470456  264.610426
..               ...        ...        ...         ...
321  8cbc6b2817631ff -33.690697  19.414593  269.398859
624  8cbc6b2817459ff -33.690460  19.414386  269.402592
374  8cbc6b2817633ff -33.690622  19.414406  269.409765
446  8cbc6b281745bff -33.690385  19.414200  269.413499
154  8cbc6b28176adff -33.690310  19.414014  269.424407

[991 rows x 4 columns]

Lastly we can make a visualisation of the distance of each part of the edge to the origin point.

df_edges.plot.hexbin(
    x='lat', 
    y='lng',
    C='distance', 
    gridsize=20, 
    cmap="viridis",
    figsize=(17,15))

output_11_1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment