笔记 | 使用 Turf.js 实现等值线/面

发布时间 2023-11-24 10:35:02作者: iNSlog

一、准备工作,所使用到的工具及API

  • Turf.js 使用的 API 如下:
    • featureCollection
    • interpolate
    • isobands
  • Leaflet.js 使用的 API 如下:
    • FeatureGroup
    • geoJSON

二、必要知识点介绍

isobands(pointGrid, breaks, options)

接收点要素集( FeatureCollection ),根据参与分级的属性和分级的数组计算出等值面并返回。

参数

参数 类型 描述
pointGrid FeatureCollection 传入的点要素集
breaks Array 分级的数组
options Object 可配置项

options 选项

属性 类型 默认值 描述
zProperty string "elevation" 参与分级的属性
commonProperties Object {} 每个要素的属性
breaksProperties Array [] GeoJSON properties passed, in order, to the correspondent isoband (order defined by breaks)

返回值

FeatureCollection <MultiPolygon> 等压线的多面要素集合

featureCollection(features, options)

接收一个或多个 Feature,创建并返回他们的要素集( FeatureCollection )。

参数

参数 类型 描述
features Array 要素数组
options Object 可配置项

options 选项

属性 类型 默认值 描述
bbox (Array) 边界框
id (string|number) 标识符

返回值

FeatureCollection 要素集合

【重要方法】interpolate(points, cellSize, options)

接收一组点要素集,使用 反向距离加权(IDW) 方法估算并返回要素集。

参数

参数 类型 描述
points FeatureCollection 传入的要素集
cellSize number 每个网格点之间的距离
options Object 可配置项

options 选项

属性 类型 默认值 描述
gridType string "square" 出参要素集的要素类型,可选值有:"square"(矩形)、"point"(点)、"hex"(六边形)、"triangle"(三角形)
property string "elevation" 参与计算的属性
units string "kilometers" 单位,可选的有 degrees、radians、miles、kilometers
weight number 1 调节距离衰减权重的指数

返回值

FeatureCollection <(Point|Polygon)> 具有插值“属性”的点或多边形网格

三、示例

引入依赖

import { featureCollection, interpolate, isobands } from '@turf/turf';
import { FeatureGroup, geoJSON } from 'leaflet';

核心方法

/**
 * @typedef {FeatureGroup} layer 负责渲染等值线的图层
 * @property {Array} features  关键点集合
 */
const setIsoline = (layer, features) => {
  // 准备工作,创建 options
  const breaks = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
  const interpolateOptions = {
    gridType: 'points',
    property: 'value',
    units: 'degrees',
    weight: 20
  };
  const isobandsOptions = {
    zProperty: 'value',
    commonProperties: {
      'fill-opacity': 0.8
    },
    breaksProperties: [
      { fill: '#1F196D7F' },
      { fill: '#31369599' },
      { fill: '#005EFFB2' },
      { fill: '#1E90A8CC' },
      { fill: '#00B457E5' },
      { fill: '#28E156FF' },
      { fill: '#B7FF01FF' },
      { fill: '#FFC800FF' },
      { fill: '#FF610CFF' },
      { fill: '#D13438FF' },
      { fill: '#A01798FF' }
    ]
  };
  // 准备工作结束

  // 将散点合并成要素集
  const points = featureCollection(features);
  // 使用反向距离加权(IDW)方法进行运算
  const grid = interpolate(points, 0.0005, interpolateOptions); 
  // 根据参与分级的属性和分级的数组计算出等值面
  const isobandsData = isobands(grid, breaks, isobandsOptions);
  const intersection = featureCollection(isobandsData.features);

  // 将等值面添加到对应图层中
  geoJSON(intersection, {
    style: feature => {
      return {
        color: feature.properties.fill,
        weight: 2,
        opacity: 1,
        fillColor: feature.properties.fill,
        fillOpacity: 0.8,
        stroke: true,
        fill: true
      };
    }
  }).addTo(layer);

  // 图层沉底,以免遮挡地图其他信息
  layer.bringToBack();
};

使用

const IsolineLayer = new FeatureGroup();
const pointList = [];
for(let i=0; i < 10; i++) {
  pointList.push(
    {
      type: 'Feature', // 类型
      properties: {
        value: 0 // 关键点数值
      },
      geometry: shape // geometry 信息
    }
  )
}

setIsoline(IsolineLayer, pointList);