Newer
Older
HuangJiPC / src / utils / gis / rainkriging.js
@zhangdeliang zhangdeliang on 21 Jun 3 KB update
const ATTRIBUTES = {
  kriging: {
    defaultConfig: {
      fields: { value: 'value', color: 'color' },
      model: 'spherical', //model还可选'gaussian','spherical',exponential
      sigma: 0,
      alpha: 100,
      levels: [
        { value: 0, color: 'rgba(169,240,145,0.4)' },
        { value: 5, color: 'rgba(108, 208, 89,0.4)' },
        { value: 10, color: 'rgba(62,185,63,0.4)' },
        { value: 15, color: 'rgba(80, 191, 167,0.4)' },
        { value: 25, color: 'rgba(97,184,253,0.4)' },
        { value: 35, color: 'rgba(0, 117, 255,0.4)' },
        { value: 50, color: 'rgba(1,0,253,0.4)' },
        { value: 75, color: 'rgba(172, 42, 254,0.4)' },
        { value: 100, color: 'rgba(250,0,252,0.4)' },
      ],
    },
  },
};

/***
 * 根据点位信息获取空间插值GeoJson
 * @param geojson
 * @param boundary 边界范围
 * @param options kriging 相关参数
 * @returns {VectorLayer<VectorSourceType>}
 */
export function getKrigingByPoints(geojson, boundary, options = {}) {
  let [levels, colors] = [[], []];
  geojson = geojson || { features: [] };
  options.model = options.model || ATTRIBUTES.kriging.defaultConfig.model;
  options.sigma = options.sigma || ATTRIBUTES.kriging.defaultConfig.sigma;
  options.alpha = options.alpha || ATTRIBUTES.kriging.defaultConfig.alpha;
  options.levels = options.levels || ATTRIBUTES.kriging.defaultConfig.levels;
  options.fields = options.fields || ATTRIBUTES.kriging.defaultConfig.fields;
  options.levels = _.sortBy(options.levels, (level) => Number(level[options.fields.value]));

  options.levels.forEach((level) => {
    levels.push(level[options.fields.value]);
    colors.push(level[options.fields.color]);
  });

  const gridFeatureCollection = (grid) => {
    let range = grid.zlim[1] - grid.zlim[0];
    let i, j, x, y, z;
    let n = grid.length; // 列数
    let m = grid[0].length; //行数
    let pointArray = [];
    let sum = levels.reduce((a, b) => a + b);
    for (i = 0; i < n; i++) {
      for (j = 0; j < m; j++) {
        x = i * grid.width + grid.xlim[0];
        y = j * grid.width + grid.ylim[0];
        // z = (grid[i][j] - grid.zlim[0]) / range;
        // if (z < 0.0)  z = 0.0
        // if (z > 1.0) z = 1.0
        pointArray.push(turf.point([x, y], { value: grid[i][j] || 0 }));
      }
    }
    return pointArray;
  };
  const randomInteger = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
  let [lngs, lats, values] = [[], [], []];
  if (!!!geojson.features.length)
    geojson = turf.randomPoint(100, {
      bbox: [113.75048547379058, 30.181701862639972, 114.23892734382642, 30.545337595017667],
    });
  geojson.features.forEach((point) => {
    let arr = turf.getCoord(point);
    lngs.push(arr[0]);
    lats.push(arr[1]);
    values.push(point.properties[options.fields.value] ?? randomInteger(0, 100));
  });

  let extent = turf.bbox(boundary);
  let krigingTrain = kriging.train(values, lngs, lats, options.model, options.sigma, options.alpha);
  let krigingGrid = kriging.grid(turf.getCoords(boundary.features[0]), krigingTrain, (extent[2] - extent[0]) / 200);
  let collection = turf.featureCollection(gridFeatureCollection(krigingGrid));
  let isobands = turf.isobands(collection, levels, { zProperty: 'value' });
  isobands.features.forEach(
    (feature) =>
      (feature.properties.color =
        colors[
          levels.indexOf(Number(feature.properties.value.split('-')[feature.properties.value.split('-').length - 2]))
        ])
  );
  isobands.features.push(turf.polygon(turf.getCoords(boundary.features[0]), { color: colors[0] }));
  isobands.features.sort((a, b) => turf.area(b) - turf.area(a));
  return isobands;
}