使用turf.js和openlayers配合生成等值面
turf.js官网:https://turfjs.org/ 中文网:https://turfjs.fenxianglu.cn/
1.npm安装turf.js:npm install @turf/turf
2.引入:
import Point from 'ol/geom/Point';
import Feature from 'ol/Feature';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import { Stroke, Style, Icon, Text as TextStyle, Circle as CircleStyle, Fill } from 'ol/style.js';
import Select from 'ol/interaction/Select';
import { click, pointerMove } from 'ol/events/condition.js';
import GeoJSON from 'ol/format/GeoJSON';
// import {featureCollection,interpolate,isobands,flatten,randomPoint,bbox,featureEach,buffer,intersect} from '@turf/turf';
import * as turf from '@turf/turf'
3.需要的数据:点数据:包括点的x,y坐标和一个用来差值的字段值,面数据用于边界修剪。如果不进行边界的修剪生成的等值面就是点集的最大边界作为边界。
let features: any = data.map(i => {//从data中获取有效数据生成geojson格式的对象。这里的data是一个对象的数组,这个对象中包含属性long(即x),lat(即y),drop(即差值字段)
return {
type: 'Feature',
properties: {
value: i.drop
},
geometry: {
type: 'Point',
coordinates: [i.long, i.lat]
}
}});
let points= turf.featureCollection(features);//根据上面的geojson数组生成一个feature集合
let interpolate_options: any = {//设置生成网格的参数
gridType: 'points',//使用的几何数据类型
property: 'value',//插值使用的字段
units: 'degrees',//横纵坐标的单位
weight: 5//插值字段的值的权重
};
let grid = turf.interpolate(points, 0.01, interpolate_options);//生成网格,0.01是网格的大小
let isobands_options = {//根据上面的网格值生成等值面的参数
zProperty: 'value',//同样表示插值的字段名
breaksProperties: [//设置分段后各个段使用的颜色
{ fill: 'rgba(240,255,255,0.8)'},
{ fill: 'rgba(144,238,144,0.8)'},
{ fill: 'rgba(144,238,144,0.8)'},
{ fill: 'rgba(52,101,255,0.8)'},
{ fill: 'rgba(255,255,1,0.8)'},
{ fill: 'rgba(254,153,0,0.8)'},
{ fill: 'rgba(218,46,42,0.8)'},
]
};
let isobandData = turf.isobands(//根据上面的网格生成等值面
grid,
[-10,-5,0, 10,30,50,1000],//根据上面的插值字段的值来进行分段的依据,即这个中间的每一段就设置为对应上面设置的颜色
isobands_options
);
//这里我们就可以将isobandData这个数据用openlayers生成图层加载到地图上了:
let vectorSource = new VectorSource({
features: new GeoJSON().readFeatures(isobandData ),
});
let vectorLayer = new VectorLayer({
source: vectorSource,
style: (feature) => {
return new Style({
fill: new Fill({
color: feature.values_.fill,
}),
});
},
});
this.map.addLayer(vectorLayer);
//我们也可以在将上面生成的等值面再用一个我们的边界进行裁剪
let intersectionFeatures: any = [];
let boundaries = turf.flatten(bounderyJson);//bounderyJson是一个面类型的按照geojson的格式生成的一个对象作为边界来进行裁剪,你可以自己按照geojson的字符串格式组织好string再用JSON.parse();方法生成对象。这个geojson的字符串可以直接使用wfs返回的数据。
isobandData.features.forEach(function (layer1) {//遍历裁剪
boundaries.features.forEach(function (layer2:any) {
let intersection = null;
try {
intersection = turf.intersect(layer1, layer2);
} catch (e) {
layer1 = turf.buffer(layer1, 0);
intersection = turf.intersect(layer1, layer2);
}
if (intersection != null) {
intersection.properties = layer1.properties;
intersection.id = Math.random() * 100000;
intersectionFeatures.push(intersection);
}
});
});
let intersection = turf.featureCollection(intersectionFeatures);//根据裁剪后的future生成可用的future集合,然后就可以将这个集合作为geojson的方式用openlayers加载到地图上了
//加载到地图上的方式和上面加载未裁剪的等值面图一致,这里就先注释掉了
// let vectorSource = new VectorSource({
// features: new GeoJSON().readFeatures(intersection),
// });
// let vectorLayer = new VectorLayer({
// source: vectorSource,
// style: (feature) => {
// return new Style({
// fill: new Fill({
// color: feature.values_.fill,
// }),
// });
// },
// });
// this.map.addLayer(vectorLayer);