map In the last two years we created several projects . When you do projects like this it's a common task that you have to process geospatial data before you can use it. You have to filter it, clean it up, aggregate it, analyze it, etc. There are tools like QGIS that help you to do these tasks, but for me as a web developer it was always a hassle to start this heavy UI when I just want to find and save points that are in a certain polygon for example.

TURF.js to the rescue

At some point I stumbled upon TURF.js . As they point out on their website TURF does "advanced geospatial analysis for browsers and node". I use it a lot in my daily work and so I want to share some real world examples with you. If you are interested in using TURF in the browser there is a good introduction you can check out. This article is about how to use TURF in combination with Node.js.

The very basics

LineString , Polygon , MultiPolygon , and so on). In order to run the following examples you need node >= 5 and these modules: If you want to process some data with TURF you always have to convert it to GeoJSON, because TURF " expects the data to be standard WGS84 longitude, latitude coordinates ". Luckily TURF offers helper functions to convert all the different types (, and so on). In order to run the following examples you need node >= 5 and these modules:

npm install turf d3-dsv --save

Measure distances

In a recent project we started with a data set containing city names and their centers (longitude,latitude). We also wanted to show the distance of each city to Berlin so we used TURF to add these values.

For this task we use the functions point and distance . The point function simply converts an array (longitude,latitude) to a GeoJSON representation. The distance function returns the distance in kilometers of the two passed points. It also takes a third parameter that can be degrees, radians, miles, or kilometers. So if you have a CSV file that contains the columns "longitude" and "latitude" and you want to add a "distance" column, you could do something like this:

const Fs = require ( 'fs' ) ; const Turf = require ( 'turf' ) ; const D3Dsv = require ( 'd3-dsv' ) ; const CENTER = Turf . point ( [ 13.4 , 52.52 ] ) ; const csvInput = Fs . readFileSync ( './cities.csv' ) . toString ( ) ; const jsonData = D3Dsv . csvParse ( csvInput ) ; jsonData . forEach ( ( el ) => { const dataPoint = Turf . point ( [ el . longitude , el . latitude ] ) ; el . distance = Turf . distance ( CENTER , dataPoint ) ; } ) ; Fs . writeFile ( './cities-with-distances.csv' , D3Dsv . csvFormat ( jsonData ) ) ; Fs . writeFile ( './cities-with-distances.json' , JSON . stringify ( jsonData ) ) ;

Colors Of Europe Interactive Data Visualization (Zeit Online) Are you interested in a collaboration? We are specialized in creating custom data visualizations and web-based tools. Contact us Learn more Learn more

Aggregation

Let's say we have a data set with houses (points) and some districts (polygons). We don't know which house belongs to which district but we want to do some aggregation of the house data. For every district we want to calculate the minimum, maximum, sum and medium of the residents. For this we can use the aggregate function. The aggregate function takes three parameters. A feature collection of polygons, a feature collection of points and an array with definitions which type of aggregation we want to do for which field. Besides min, max, sum and median you can also calculate the average, deviation, variance and count.

const Fs = require ( 'fs' ) ; const Turf = require ( 'turf' ) ; const houses = JSON . parse ( Fs . readFileSync ( './houses.geo.json' ) ) ; const districts = JSON . parse ( Fs . readFileSync ( './districts.geo.json' ) ) ; const inputField = 'residents' ; const aggregations = [ { aggregation : 'min' , inField : inputField , outField : ` ${ inputField } _min ` , } , { aggregation : 'max' , inField : inputField , outField : ` ${ inputField } _max ` , } , { aggregation : 'sum' , inField : inputField , outField : ` ${ inputField } _sum ` , } , { aggregation : 'median' , inField : inputField , outField : ` ${ inputField } _median ` , } , ] ; const aggregated = Turf . aggregate ( districts , houses , aggregations ) ; Fs . writeFile ( './districts-aggregated.geo.json' , JSON . stringify ( Turf . featurecollection ( aggregated ) ) ) ;

If you are lazy, you could also create the array with aggregations this way:

const aggregations = [ 'min' , 'max' , 'sum' , 'median' ] . map ( ( aggregationType ) => { return { aggregation : aggregationType , inField : inputField , outField : ` ${ inputField } _ ${ aggregationType } ` , } ; } ) ;

Finding points in polygons

Image you have several points of interest but you only want to look at points in a certain neighbourhood. In order to do this you can use the within function. This function takes a feature collection of points and a feature collection of polygons. It then returns all points that are in at least on of the passed polygons.

const Fs = require ( 'fs' ) ; const Turf = require ( 'turf' ) ; const points = JSON . parse ( Fs . readFileSync ( './points.geo.json' ) ) ; const neighbourhood = JSON . parse ( Fs . readFileSync ( './neighbourhood.geo.json' ) ) ; const poisResult = Turf . within ( points , neighbourhood ) ; Fs . writeFile ( './points-within-neighbourhood.json' , JSON . stringify ( poisResult ) ) ;

What else?