The open source front-end GIS spatial analysis library introduces the combination of turf and ol

Keywords: webgis OpenLayers

preface

turf is the front-end spatial analysis library produced by mapbox. Its official website is: http://turfjs.org/
Turf library contains many functions of spatial analysis and calculation, and it is also very simple and easy to use. Compared with jsts, the official documents of turf are maintained very well and make great use of learning.

Openlayers (ol for short) is an excellent Web GIS library, which is very suitable for developing map related applications. However, the short board of openlayers is that there are few functions of spatial analysis and calculation, because its combination with turf can well solve this problem.

Next, let's look at the method used by ol in combination with turf.

1. Installation and reference

1.1 turf

The installation reference of turf can be referred to< Introduction to open source front-end GIS spatial analysis library (I) jsts and turf>
If you want to import cdn, you can use the following address:

<script src="https://cdn.bootcdn.net/ajax/libs/Turf.js/6.5.0/turf.min.js"></script>

1.2 openlayers

html

<!-- introduce ol-->
<link href="https://cdn.bootcdn.net/ajax/libs/ol3/4.6.5/ol.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/ol3/4.6.5/ol.js"></script>

NPM installation

npm i ol 

It should be noted that ol does not support running in the Node environment and can only be run on the browser side.

2. ol combined with turf

Take an example:
Draw the ecological red line within 50m around a lake on the map, and the lake range is known.
Students familiar with gis know that the buffer operation of gis is used at this time. There is no cache related method in openlayers, so turf is used here.
Let's look at the code:

// view
var view = new ol.View({
  projection: 'EPSG:4326',
  zoom: 14,
  center:  [0, 0]
})

// Base map
var baseLayer = new ol.layer.Tile({
  source: new ol.source.XYZ({
    url:'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}'
  })
})

// Vector Layer 
var vectorLayer = new ol.layer.Vector({
  source: new ol.source.Vector(),
  style: function (ft) {
    var name = ft.get('name')
    var color = name === 'buffer' ? '#F44336' : '#3F51B5'
    return new ol.style.Style({
      fill: new ol.style.Fill({
        color
      })
    })
  },
  // Define the rendering order, who is older and who is on top
  renderOrder: function (ft1, ft2) {
    return ft1.get('order') - ft2.get('order')
  }
})

// Map object
var map = new ol.Map({
  target: 'map',
  view: view,
  layers: [baseLayer,vectorLayer],
})

// Lake test data
var data ={
  "type": "FeatureCollection",
  "name": "12",
  "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
  "features": [
    { "type": "Feature", "properties": { "name": 'water'}, "geometry": { "type": "Polygon", "coordinates": [ [ [ 106.4212556, 27.9028272 ], [ 106.4215743, 27.902787 ], [ 106.4218625, 27.9028406 ], [ 106.4221053, 27.9029747 ], [ 106.4224088, 27.9029613 ], [ 106.4226515, 27.9028406 ], [ 106.4224543, 27.9023445 ], [ 106.4225908, 27.9021031 ], [ 106.4228639, 27.9019959 ], [ 106.4231674, 27.9015131 ], [ 106.4234405, 27.9014059 ], [ 106.423744, 27.9014327 ], [ 106.4240474, 27.9018618 ], [ 106.4243054, 27.9019556 ], [ 106.4245937, 27.901969 ], [ 106.4253978, 27.9023579 ], [ 106.4258985, 27.9030015 ], [ 106.4260047, 27.9032429 ], [ 106.4260502, 27.9037926 ], [ 106.4262778, 27.904262 ], [ 106.426991, 27.9047983 ], [ 106.4270668, 27.9050531 ], [ 106.4270972, 27.9058174 ], [ 106.4274613, 27.9070375 ], [ 106.4274006, 27.9072789 ], [ 106.4271275, 27.9077214 ], [ 106.4272641, 27.9079493 ], [ 106.4276131, 27.9079627 ], [ 106.4278103, 27.908137 ], [ 106.4283262, 27.908794 ], [ 106.4284172, 27.9090354 ], [ 106.4283262, 27.9093303 ], [ 106.4281744, 27.9095315 ], [ 106.4282048, 27.9097862 ], [ 106.4284779, 27.9098935 ], [ 106.4292517, 27.9093974 ], [ 106.429191, 27.9091426 ], [ 106.429009, 27.9089281 ], [ 106.4289331, 27.9086465 ], [ 106.4289027, 27.9076007 ], [ 106.4288117, 27.9073593 ], [ 106.4283565, 27.9067023 ], [ 106.4283565, 27.9064207 ], [ 106.4286145, 27.9058978 ], [ 106.4287965, 27.9056967 ], [ 106.4293428, 27.9055224 ], [ 106.4296159, 27.9056296 ], [ 106.4299497, 27.9056565 ], [ 106.4300407, 27.9054017 ], [ 106.4299497, 27.9051603 ], [ 106.4296917, 27.9050397 ], [ 106.429449, 27.9049458 ], [ 106.4286145, 27.9048251 ], [ 106.428402, 27.9046776 ], [ 106.4277344, 27.9035245 ], [ 106.4276282, 27.9032563 ], [ 106.4276131, 27.9029747 ], [ 106.4278558, 27.9019422 ], [ 106.4277344, 27.9017143 ], [ 106.42866, 27.9012718 ], [ 106.4288269, 27.9010706 ], [ 106.4282503, 27.9011243 ], [ 106.4278255, 27.9014059 ], [ 106.4275524, 27.9014863 ], [ 106.4272792, 27.901379 ], [ 106.4271123, 27.9009097 ], [ 106.4267785, 27.900494 ], [ 106.4264447, 27.8997565 ], [ 106.4264447, 27.8995018 ], [ 106.4266723, 27.8987374 ], [ 106.4270668, 27.8983083 ], [ 106.4275068, 27.8976244 ], [ 106.4277648, 27.8968467 ], [ 106.42778, 27.8965919 ], [ 106.4276434, 27.8963639 ], [ 106.4267027, 27.8972758 ], [ 106.4263992, 27.8977049 ], [ 106.4261261, 27.8976244 ], [ 106.4258075, 27.8976244 ], [ 106.4255951, 27.8980804 ], [ 106.4253371, 27.8982279 ], [ 106.4247757, 27.8982279 ], [ 106.424715, 27.898496 ], [ 106.4244571, 27.8985631 ], [ 106.4241536, 27.8985631 ], [ 106.4238502, 27.8985363 ], [ 106.4232433, 27.8983754 ], [ 106.4215894, 27.8989251 ], [ 106.4214984, 27.8991665 ], [ 106.4214529, 27.9005477 ], [ 106.4213618, 27.900789 ], [ 106.4209218, 27.9014193 ], [ 106.4212556, 27.9028272 ] ] ] } }
  ]
}
  
// Present test data
var format = new ol.format.GeoJSON()
var fts = format.readFeatures(data)
var ft = fts[0]
ft.setProperties({
  order: 3
})
vectorLayer.getSource().addFeature(ft)
view.fit(ft.getGeometry())

// Use turf to create a buffer
var turfRegion = turf.polygon(data.features[0].geometry.coordinates)
console.log(turfRegion)
var buffer = turf.buffer(turfRegion, 0.05, {units: 'miles'})

// Convert turf cache results to ol.Feature objects
var olBuffer = format.readFeature(buffer)
olBuffer.setProperties({
  name: 'buffer',
  order: 2
})
vectorLayer.getSource().addFeature(olBuffer)

result:

The blue coverage area is the lake range, and the red is the red line range required by the title.
openlayers and turf in the example are introduced through cdn.
In the example, the following operations are mainly performed.

  1. The lake data given is in geojson format;
  2. Read and display the data through openlayers;
  3. A buffer is created by reading the polygon in the data through turf.
  4. Convert the buffer data in turf format into ol.Feature object for map display.

be careful
When writing the example, I encountered some small problems.
When using turf.buffer to create a buffer, the units attribute in the third parameter of the function defines the length unit, which seems to have little effect in practical application.
The data I give is the data of wgs84 coordinate system. The length unit I specify in the function is miles (meters), and the buffer range is set to 50. The result is large and almost covers the whole earth. Therefore, the 50m buffer range in the above example is not accurate.
At first, I thought it was a coordinate system problem, so I transformed the data coordinate system into 3857 projection coordinate system. After buffering, the result is a pile of coordinates in suspected 4326 coordinate system.

var data1 = {
  "type": "FeatureCollection",
  "name": "14",
  "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::3857" } },
  "features": [
    { "type": "Feature", "properties": { "OSM_ID": null, "OSM_WAY_ID": "355971874", "NAME": null, "TYPE": null, "CRAFT": null, "NATURAL": "water" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 11846759.98297281190753, 3236728.037491085939109 ], [ 11846795.4604945294559, 3236722.973750801291317 ], [ 11846827.542771777138114, 3236729.725404934026301 ], [ 11846854.571144139394164, 3236746.617151281796396 ], [ 11846888.356609594076872, 3236744.92923534149304 ], [ 11846915.373850012198091, 3236729.725404934026301 ], [ 11846893.421646423637867, 3236667.234942891635001 ], [ 11846908.616756919771433, 3236636.827472372446209 ], [ 11846939.018109858036041, 3236623.324259491171688 ], [ 11846972.803575312718749, 3236562.509582209866494 ], [ 11847003.204928247258067, 3236549.006442959420383 ], [ 11847036.990393701940775, 3236552.382226516958326 ], [ 11847070.764727214351296, 3236606.432665946427733 ], [ 11847099.485155833885074, 3236618.247961841057986 ], [ 11847131.578565029427409, 3236619.93586208904162 ], [ 11847221.090567579492927, 3236668.922849210910499 ], [ 11847276.828236617147923, 3236749.992983783595264 ], [ 11847288.65036654099822, 3236780.400706783868372 ], [ 11847293.715403370559216, 3236849.643401233013719 ], [ 11847319.051719473674893, 3236908.77142351353541 ], [ 11847398.444780306890607, 3236976.326825576368719 ], [ 11847406.88279770873487, 3237008.423001928254962 ], [ 11847410.26691023632884, 3237104.699387811124325 ], [ 11847450.798336829990149, 3237258.392827218864113 ], [ 11847444.041243735700846, 3237288.80168459797278 ], [ 11847413.639890801161528, 3237344.543034738395363 ], [ 11847428.84613324701786, 3237373.251493629999459 ], [ 11847467.696635531261563, 3237374.939487393014133 ], [ 11847489.648839114233851, 3237396.896022306289524 ], [ 11847547.07856441475451, 3237479.658494292292744 ], [ 11847557.208638079464436, 3237510.067845435813069 ], [ 11847547.07856441475451, 3237547.216726473998278 ], [ 11847530.180265713483095, 3237572.56217240029946 ], [ 11847533.564378233626485, 3237604.647155913058668 ], [ 11847563.965731168165803, 3237618.163938366807997 ], [ 11847650.104753144085407, 3237555.669402255676687 ], [ 11847643.347660057246685, 3237523.571936964523047 ], [ 11847623.087512725964189, 3237496.551170205697417 ], [ 11847614.638363376259804, 3237461.077834676485509 ], [ 11847611.254250859841704, 3237329.33853537356481 ], [ 11847601.124177195131779, 3237298.929587538354099 ], [ 11847550.451544987037778, 3237216.168213179334998 ], [ 11847550.451544987037778, 3237180.695607519708574 ], [ 11847579.171973612159491, 3237114.8271539285779 ], [ 11847599.432120937854052, 3237089.495156041812152 ], [ 11847660.2459587585181, 3237067.539116402622312 ], [ 11847690.647311693057418, 3237081.042769411578774 ], [ 11847727.805757720023394, 3237084.431281455326825 ], [ 11847737.935831379145384, 3237052.334926092065871 ], [ 11847727.805757720023394, 3237021.926596360746771 ], [ 11847699.085329094901681, 3237006.735053564887494 ], [ 11847672.068088676780462, 3236994.906824260484427 ], [ 11847579.171973612159491, 3236979.702714981045574 ], [ 11847555.516581816598773, 3236961.122737025842071 ], [ 11847481.199689762666821, 3236815.872270544525236 ], [ 11847469.377559846267104, 3236782.088627113960683 ], [ 11847467.696635531261563, 3236746.617151281796396 ], [ 11847494.713875949382782, 3236616.560061801224947 ], [ 11847481.199689762666821, 3236587.853196847718209 ], [ 11847584.237010441720486, 3236532.114941515494138 ], [ 11847602.816233457997441, 3236506.771430517546833 ], [ 11847538.62941506318748, 3236513.53557372558862 ], [ 11847491.340895377099514, 3236549.006442959420383 ], [ 11847460.939542442560196, 3236559.133796146139503 ], [ 11847430.527057554572821, 3236545.618064034730196 ], [ 11847411.947834543883801, 3236486.504213336855173 ], [ 11847374.789388516917825, 3236434.14212672971189 ], [ 11847337.630942489951849, 3236341.246208750642836 ], [ 11847337.630942489951849, 3236309.164199478924274 ], [ 11847362.967258594930172, 3236212.880837032105774 ], [ 11847406.88279770873487, 3236158.831958169583231 ], [ 11847455.863373659551144, 3236072.68924510711804 ], [ 11847484.583802284672856, 3235974.732328060548753 ], [ 11847486.275858547538519, 3235942.638585737440735 ], [ 11847471.069616103544831, 3235913.920544414781034 ], [ 11847366.351371115073562, 3236028.780476970598102 ], [ 11847332.565905654802918, 3236082.828840179368854 ], [ 11847302.1645527202636, 3236072.68924510711804 ], [ 11847266.698162958025932, 3236072.68924510711804 ], [ 11847243.053903110325336, 3236130.126057209447026 ], [ 11847214.333474487066269, 3236148.704902401193976 ], [ 11847151.83871235512197, 3236148.704902401193976 ], [ 11847145.081619268283248, 3236182.474380094092339 ], [ 11847116.372322585433722, 3236190.926209496334195 ], [ 11847082.586857130751014, 3236190.926209496334195 ], [ 11847048.812523625791073, 3236187.550515454728156 ], [ 11846981.252724664285779, 3236167.283772912807763 ], [ 11846797.141418838873506, 3236236.523352698422968 ], [ 11846787.01134517788887, 3236266.929930203594267 ], [ 11846781.946308348327875, 3236440.906233894173056 ], [ 11846771.805102733895183, 3236471.300671197939664 ], [ 11846722.82452679052949, 3236550.694334634579718 ], [ 11846759.98297281190753, 3236728.037491085939109 ] ] ] } }
  ]
}

var turfRegion = turf.polygon(data1.features[0].geometry.coordinates)
var buffer = turf.buffer(turfRegion, 50, {units: 'miles'})
console.log('EPSG:3857', buffer)


What's the problem? You need to debug the source code later

3. geojson data format

Turf reading and writing data is the geojson data format used by itself. ol.format.GeoJSON in ol has methods to support reading and writing geojson data. Therefore, taking geojson data as a bridge, data interaction can be carried out between OL and turf. The above example also makes use of this.

3.1 using ol to read geojson

Whether you use ol to read or write geojson, you can instantiate an ol.format.GeoJSON object first.

var format = new ol.format.GeoJSON()

When we switch from turf object to ol object, the data object conversion process is as follows:
turf -> geojson -> ol.Feature,ol.geom.Geometry
For reading operations, please refer to the following methods.

  • readFeature
    Read the feature from geojson, and the return value is an ol.Feature object.
  • readFeatures
    Read the feature set from geojson, and the return value is an array containing ol.Feature objects.
  • readGeometry
    Read the geometric object from geojson, and the return value is an ol.geom.Geometry object.

3.2 using ol to write geojson

When the Feature or Geometry object of ol needs to be converted into geojson, and then turf can operate, the data conversion process is as follows:
ol.Feature,ol.geom.Geometry > geojson - >turf
The following write operations can be used in this process.

  • writeFeature
    Convert an ol.Feature object to a geojson string.
  • writeFeatures
    Convert an array composed of ol.Feature objects into a string in geojson format.
  • writeGeometry
    Convert an ol.geom.Geometry object to a geojson string.

The above method name, followed by Object, is a new method. The conversion result is given to the corresponding geojson Object.

The author wrote a js package according to the above method: ol-turf-parse , preview address: https://www.npmjs.com/package/ol-turf-parse .
If you think the above method is troublesome, you can try this bag.
If you are in a front-end engineering project, you can use the following command for installation.

npm i ol-turf-parse

In this package, two methods ol2turf and turf2ol are provided for OL to turf and turf to ol, respectively.
Example:

let point = [0, 0]
let ft = new Feature({
  geometry: new Point(point)
})
ft.setProperties({
  name: 'ol-turf'
})
let r = ol2turf(ft)
console.log(r)

output

{
  type: 'Feature',
  geometry: { type: 'Point', coordinates: [ 0, 0 ] },
  properties: { name: 'ol-turf' }
}

Posted by wcl99 on Mon, 04 Oct 2021 15:42:14 -0700