Hands On
Data Layers

Create a WKT File Using HERE Data Layers and Geopandas

By Shruti Kuber | 26 October 2020

Try HERE Maps

Create a free API key to build location-aware apps and services.

Get Started

A few weeks ago, I was working on a demo where I drew geofences around brick and mortar stores. When my user is near this geofence, they get a notification about the offers in the store. Sounds cool doesn't it? Step 1 of this demo is to create a geofence in the WKT format. Normally a geofence is created by manually drawing polygons around a place and extracting them as WKTs. I was looking for a better method to automate this. This is when I came across Geopandas. Geopandas is a Python library that works specifically with geospatial data. Couple this with the Buildings HERE Data Layer and you can get geofences for different buildings in a city within minutes.

I am assuming you already have downloaded the Buildings layer of your favorite city in your Data Hub. If not, take a quick look at Ray's blog post and then come back. Now you can download this file directly from the Data Hub, although if it is too big a file, you will need to use the Data Hub CLI. So open your terminal and install the CLI. The prerequisites for this installation are Node.js and npm.


    npm install -g @here/cli
        

Configure the Data Hub CLI with the same login and password that you used to create the Data Layers.


    here configure account
        

You can list all the layers you have in your Data Hub using here xyz list.

id title description
7Vzz48SR Berlin-Buildings-v60 Space for Berlin city, version 60 of Buildings layer

You will see that every layer has an id. You can now download the Buildings layer using its id.


        here xyz show -r YOUR_SPACE_ID --all >Berlin-Buildings.geojson
        

Once you have the layer, the real fun begins. As I mentioned, we are going to use Python to process this file. With it, we are going to use the geopandas, and shapely libraries. Be sure to have them installed in your environment. The first step now is to read the Buildings file and see what the structure of the objects within is. I used a Jupyter notebook for this example. You can also simply open a file called toWKT.py and start typing the code below.


import geopandas as gpd
import json
import shapely.ops as shp

buildings = gpd.read_file('MapData_GeoJSON/Houston-Buildings.geojson')

print(buildings.head(n=5))
        

Screen Shot 2020-10-22 at 5.08.04 PM

You will see that the Geopandas library converts the GeoJSON file into a GeoDataFrame and the objects within it, into DataSeries. Visually it is tabular where every column is a feature within the feature collection. In this table you will see a column named 'geometry' which has the polygons of the footprints of these buildings. Another GeoSeries or column that we are interested in is the one named 'buildingType'.
If you expand the buildingType object, it looks something like this. [ { "type": 2005450, "typeDescription": "Residential Building\\/Landmark" } ]. Let's see the unique building types available in this dataset.


unq = buildings.drop_duplicates(subset=["buildingType"])
for index, row in unq.iterrows():
    typedes = row["buildingType"]
    o = json.loads(typedes)
    if(row["names"] != None):
        print(o[0]["typeDescription"])
        

Business/Commerce Building/Landmark
Cultural Building/Landmark
Government Building/Landmark
Education Building/Landmark
Tourist Building/Landmark
Retail Building/Landmark
Historical Building/Landmark
Park/Leisure Building/Landmark
Place of Worship Building/Landmark
Medical Building/Landmark
Convention/Exhibition Building/Landmark
Transportation Building/Landmark
Sports Building/Landmark
Emergency Service Building/Landmark
Parking Building/Landmark
Unclassified Building/Landmark   
        

For the demo I was working on, I selected the 'Retail Building/Landmark' for my geofences. And now I want to store them in the WKT format. If you want to read more about what the Well-Known Text format is, head over to this blog post about WKT files. In a nutshell, it is a format to store spatial geometries or geometries which have a latitude and longitude to them. It can store POINTS, POLYGONS or LINESTRING. The elements in the file are tab delimited. The header should always have the column named WKT along with other columns like name, id or any other form of data that you would like to append to this geometry. Let us create the file with its headers.


geofence_file = open(r"retail.wkt","w")
header_str = "NAME"+"\t"+"WKT"+"\n"
geofence_file.write(header_str)
        

The rows after the header then have the property of the shape and the shape itself. The way the shape is defined is with the shape-name followed by a list of coordinates. So a polygon with 5 points will be defined as POLYGON ((POINT1_Longitude POINT1_Latitude,POINT2_Longitude POINT2_Latitude,POINT3_Longitude POINT3_Latitude,POINT4_Longitude POINT4_Latitude,POINT5_Longitude POINT5_Latitude,POINT1_Longitude POINT1_Latitude,)). Notice how the first point is repeated in the end to signify the closing of the shape. So, let's extract the shapes and names of all the buildings of the type 'Retail Building/Landmark'.


for index, row in buildings.iterrows():
    typedes = row["buildingType"]
    o = json.loads(typedes)
    if(row["names"] != None):
        n = json.loads(row["names"])
        if(o[0]["typeDescription"]=="Retail Building/Landmark"):
        

Before we write these geometries to the WKT file, we need to talk about the format of the geometries in this GeoDataFrame. If you look closely, these are MultiPolygons. Although they are a perfectly acceptable format, the geofence HERE API accepts only Points, LineStrings or Polygons. Also, the shapes are preceded by a 'Z' which indicate that they are 3D shapes which include the altitude of the point as well. But if you look closely, the altitude in the shapes is always 0. E.g.MULTIPOLYGON Z(((13.37712 52.52824 0.00000,....))). Also, the multi-polygon shape has only 1 polygon within it. So, it will be easy to extract it and put it down as a single polygon. Let's go ahead and do that and then print the shapes and store names in the WKT file.


            geo = row["geometry"]
            geo2d = shp.transform(lambda x,y, z=None:(x,y),geo)
            format_str = n[0]["name"]+"\t"+str(geo2d[0])+"\n"
            print(format_str)
            geofence_file.write(format_str)
        

NAME	WKT
Karstadt	POLYGON ((13.42405043 52.48666395, 13.42498651 52.4877888, 13.42432063 52.48804738, 13.42430857 52.4880349, 13.42494224 52.48778501, 13.42472176 52.48752075, 13.42467775 52.487468, 13.42429992 52.48701514, 13.42425763 52.48696446, 13.42402932 52.4866908, 13.42335958 52.48688215, 13.42334699 52.48686501, 13.42405043 52.48666395))
Galeria Kaufhof	POLYGON ((13.43495276 52.51209543, 13.43544543 52.51271736, 13.43436342 52.51303453, 13.43387612 52.51241562, 13.43495276 52.51209543))
Mall of Berlin	POLYGON ((13.37691817 52.5099596, 13.37693541 52.50983801, 13.37714271 52.50985053, 13.37713587 52.50990756, 13.37713136 52.50993514, 13.37770245 52.51036879, 13.37894697 52.51044039, 13.37961304 52.51012148, 13.37965741 52.50985681, 13.37983327 52.50986654, 13.37977171 52.5101922, 13.37902568 52.51056459, 13.37848268 52.51053098, 13.3776097 52.51047693, 13.37694178 52.50996276, 13.37691817 52.5099596))
ZARA	POLYGON ((13.38120961 52.51095166, 13.38120392 52.51097859, 13.38120539 52.51096468, 13.38114562 52.5109643, 13.38131619 52.50991878, 13.38270233 52.51000422, 13.38264228 52.51040018, 13.38230362 52.51049331, 13.3821384 52.5109229, 13.38204952 52.51090149, 13.38193293 52.51106168, 13.38171063 52.51101843, 13.38146826 52.51099937, 13.38147395 52.51097244, 13.38152091 52.51075014, 13.38125656 52.51072935, 13.38120961 52.51095166))
        

Conclusion

We used the Geopandas library to easily parse GeoJSON files and create a geospatial layer in the WKT format. Oh, and you can find the demo I mentioned on our GitHub. Let me know how you have been using the Geopandas library in the comments section below.