cesium+turf.js:降雨量等值线图

准备工作

  1. turfjs, 空间分析(geospatial analysis)工具包,支持在浏览器和 Node.js 环境中运行,空间数据的输入输出使用 GeoJSON 编码。本文对应的版本是 turfjs@5.1.6 。
  2. 散点数据,也就是业务数据,可以是一些观测点的温度或降雨量。这里以降雨量为例

        

var rainData = [
  { name: '山东头1#水库水文站', lon: 120.436569, lat: 36.964243, value: '52.4' },
  { name: '午山水库水文站', lon: 120.287671, lat: 37.060722, value: '19.7' },
  { name: '中韩街道办事处雨量站', lon: 120.450068, lat: 36.136672, value: '11.7' },
  { name: '大石村(Q)雨量站', lon: 120.551003, lat: 36.183102, value: '81.7' },
  { name: '流清河水库水文站', lon: 120.613795, lat: 36.133937, value: '31.7' },
  { name: '晓望水库水文站', lon: 120.641786, lat: 36.246563, value: '41.7' },
  { name: '长岭雨量站雨量站', lon: 120.683333, lat: 36.166667, value: '49.7' },
  { name: '曲家沟雨量站', lon: 120.594091, lat: 36.312239, value: '10.7' },
   { name: '大石村(Q)雨量站', lon: 120.554879, lat: 37.004007, value: '81.7' },
  { name: '流清河水库水文站', lon: 120.033822, lat: 36.245937, value: '31.7' },
  { name: '晓望水库水文站', lon: 120.427773, lat: 36.465302, value: '50.7' },
  { name: '长岭雨量站雨量站', lon: 120.233758, lat: 36.427334, value: '49.7' },
  { name: '曲家沟雨量站', lon: 120.40661, lat: 36.768867, value: '13.7' },
  { name: '流清河水库水文站', lon: 119.808603, lat: 36.054676, value: '27.0' },
  { name: '流清河水库水文站', lon: 120.033823, lat: 36.497519, value: '38.9' },
  { name: '晓望水库水文站', lon: 120.420731, lat: 37.45839, value: '69.7' },
  { name: '长岭雨量站雨量站', lon: 119.733072, lat: 35.907987, value: '49.7' },
  { name: '曲家沟雨量站', lon: 19.4633, lat: 36.009421, value: '13.7' },
  { name: '流清河水库水文站', lon: 119.891767, lat:35.842613, value: '38.9' },
];
  1. 一个边界数据,用于裁剪出一幅针对某一区域干净的色斑图,格式为 GeoJSON。推荐使用 geojson.io 来查看或编辑这类数据,这里给出一个城市的 boundaries 做示例。

        请前往 下载资源中免费下载geojson 数据geojson测试数据

        

在页面中引入 import * as turf from '@turf/turf';

在页面中引入geojson数据  你本地的地址import { areaJson } from '@/assets/json/area';

加载cesium 地图  这里不做过多赘述

        let boundaries = areaJson;


        mounted(){
        // Cesium token授权
        Cesium.Ion.defaultAccessToken ='你的cesiumToken';
        // 场景地图基础配置
        viewer = new Cesium.Viewer('cesiumContainer', {
          infoBox: false, //默认弹窗控件
          geocoder: false, // 地理位置查询定位控件
          vrButton: false, //VR按钮控件
          homeButton: false, // 默认相机位置控件
          animation: false, // 控制场景动画的播放速度控件
          timeline: false, // 时间滚动条控件
          navigationHelpButton: false, // 默认的相机控制提示控件
          fullscreenButton: false, // 全屏控件
          sceneModePicker: false, //场景模式切换控件
          baseLayerPicker: false, // 底图切换控件
          selectionIndicator: false, //对象指示器控件
          imageryProvider: new Cesium.SingleTileImageryProvider({
            url: this.createColorCanvas('#0a1729F'),
            rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0),
          }),
        });
          // 添加等值线图
          this.handleInterscetion(rainData, boundaries); 

        }

利用 turf.js 处理降雨量数据

  1.  // 处理得到等值线面数据 添加到cesium地图上
        handleInterscetion(rainStation, boundaries) {
         
          let arr = rainStation.map((it) => it.value);
          let max = Math.max(...arr.filter((item) => typeof item === 'number'));
          console.log(`output->降雨最大值max`, max);
          let breakList = [];
          if (max > 100) {
            breakList = [0, 2.5, 5, 10, 25, 50, 100, max];
          } else {
            breakList = [0, 2.5, 5, 10, 25, 50, 100];
          }
          let rainfeatures = rainStation.map((i) => {
            return {
              type: 'Feature',
              properties: {
                value: i.value,
              },
              geometry: {
                type: 'Point',
                coordinates: [i.lon, i.lat],
              },
            };
          });
          //   console.log('rainfeatures', rainfeatures);
          var points = turf.featureCollection(rainfeatures);
          //   console.log('points', points);
          var interpolate_options = {
            gridType: 'points',
            property: 'value',
            units: 'degrees',
            weight: 4,
          };
          //turf.interpolate() 提供了基于 IDW(反距离权重)算法的将数据插值为格点的方法。插值的精度是由第二个参数与 interpolate_options.units 共同决定的,单位支持 degrees, radians, miles, or kilometers,IDW 要为每个格点计算所有散点的权重,计算规模是 (散点数 * 格点数),所以要在精度与性能间做好平衡。 我们将之前的散点(points)代入
          let grid = turf.interpolate(points, 0.05, interpolate_options);
          // 适当降低插值结果的精度便于显示
          grid.features.map((i) => (i.properties.value = i.properties.value.toFixed(2)));
    
          var isobands_options = {
            zProperty: 'value',
            commonProperties: {
              'fill-opacity': 0.8,
            },
            //颜色
            breaksProperties: [
              { fill: '#DCF6D3' },
              { fill: '#B2F9A0' },
              { fill: '#6CD869' },
              { fill: '#59B83D' },
              { fill: '#78B8F1' },
              { fill: '#1111F4' },
              { fill: '#ED0FED' },
            ],
          };
          let isobands = turf.isobands(grid, breakList, isobands_options);
        //这一步基于插值获得的格点绘制等值区域,并为区域配置颜色。turf.isobands() 根据 zProperty 分段,形成一些 MultiPolygon。
          boundaries = turf.flatten(boundaries);
          isobands = turf.flatten(isobands);
    
          let features = [];
        //利用准备的边界来裁剪整个色斑图
          isobands.features.forEach(function (layer1) {
            boundaries.features.forEach(function (layer2) {
              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;
                features.push(intersection);
              }
            });
          });
    
          let intersection = turf.featureCollection(features);
    
    
          //先清除所有的实体
          viewer.entities.removeAll();
          Cesium.GeoJsonDataSource.load(intersection).then((dataSource) => {
            let entities = dataSource.entities.values;
            for (let i = 0; i < entities.length; i++) {
              let entity = entities[i];
              let positions = entity.polygon.hierarchy._value.positions;
              //设置面轮廓
              entity.polyline = new Cesium.PolylineGraphics({
                positions: positions,
                // clampToGround: true,	// 贴地
                width: 1,
                // material: Cesium.Color.WHITE.withAlpha(0.01)
              });
              entity.polygon.outline = false;
              entity.polygon.height = 1800;
              // entity.polygon.height = 10;
              viewer.entities.add(entity);
            }
          });
          
        },

<think>根据错误信息,问题是在渲染过程中片段着色器编译失败,错误日志为null。这通常与显卡驱动或WebGL环境有关,但也可能是由于Cesium的某些特定问题。以下是一些可能的解决方案: 1. **更新显卡驱动**:确保你的显卡驱动是最新的。 2. **检查WebGL支持**:访问[WebGL Report](https://webglreport.com/)检查浏览器是否支持WebGL 2.0(Cesium推荐使用WebGL 2.0)。 3. **尝试其他浏览器**:比如Chrome或Firefox的最新版本。 4. **检查Cesium版本**:确保使用的是最新版本的Cesium。如果使用的是本地服务器,尝试更新Cesium库。 5. **检查代码中是否有自定义着色器**:如果有自定义着色器代码,请检查其正确性。 6. **简化场景**:如果场景复杂,尝试逐步移除实体,以确定是哪个实体导致的问题。 7. **硬件加速**:确保浏览器启用了硬件加速。 8. **清除缓存**:清除浏览器缓存或尝试无痕模式。 由于错误信息中提到了片段着色器编译失败,并且日志为null,这可能是由于着色器代码中的错误,但Cesium未能捕获具体错误。可以尝试以下步骤: - 在Cesium初始化时开启调试: ```javascript viewer = new Cesium.Viewer('cesiumContainer', { contextOptions: { webgl: { preserveDrawingBuffer: true // 有助于调试 } } }); ``` - 使用Cesium的调试工具:在浏览器控制台中输入`viewer.scene.debugShowWebGLErrors = true;`,这可能会提供更多错误信息。 如果以上方法都不能解决问题,可能是由于特定硬件兼容性问题。可以尝试在Cesium初始化时设置`requestWebGL1: true`来降级到WebGL 1.0: ```javascript viewer = new Cesium.Viewer('cesiumContainer', { contextOptions: { webgl: { requestWebGL1: true } } }); ``` 另外,检查控制台是否有其他错误,比如资源加载失败(如地形、影像等),这些有时也会间接导致渲染问题。 由于错误发生在渲染过程中,且具体错误信息不足,需要逐步排查。如果问题仍然存在,可以考虑在Cesium的GitHub仓库中提交issue,提供详细的错误信息和环境描述。 §§相关问题§§ 1. 如何获取更详细的WebGL错误信息以帮助诊断片段着色器编译失败的问题? 2.Cesium中,如何降级到WebGL 1.0以解决兼容性问题? 3. 除了更新显卡驱动,还有哪些方法可以解决WebGL渲染问题? 4. 如何检查浏览器是否支持WebGL 2.0? 5.Cesium中,如何开启调试模式以获取更多的渲染错误信息?</think>这个错误表明 Cesium 在渲染过程中遇到了片段着色器编译失败的问题。着色器是 WebGL 的核心组件,用于控制图形渲染效果。以下是对此问题的分析和解决方案: ### 错误原因分析 1. **着色器编译失败**: - 片段着色器负责计算每个像素的颜色 - 错误日志为 `null` 表示浏览器未提供具体错误信息 - 常见于 WebGL 兼容性问题或着色器代码错误 2. **可能原因**: - 显卡驱动过时或不兼容 - 浏览器 WebGL 实现存在缺陷 - Cesium 版本与当前环境不兼容 - 自定义着色器代码错误 - 硬件加速被禁用 ### 解决方案 #### 1. 基础检查 ```javascript // 检查WebGL支持 if (!Cesium.FeatureDetection.supportsWebgl()) { console.error("浏览器不支持WebGL"); } // 检查着色器编译支持 const context = scene.context; console.log("最大纹理尺寸:", context.maximumTextureSize); console.log("着色器精度:", context.fragmentShaderPrecision); ``` #### 2. 浏览器端修复 ```javascript // 在Cesium初始化时添加错误处理 const viewer = new Cesium.Viewer('cesiumContainer', { contextOptions: { webgl: { preserveDrawingBuffer: true // 有助于调试 } } }); // 启用详细错误日志 viewer.scene.debugShowWebGLErrors = true; ``` #### 3. 代码级修复 ```javascript // 1. 降级到WebGL 1.0 const viewer = new Cesium.Viewer('cesiumContainer', { contextOptions: { webgl: { requestWebGL1: true // 使用WebGL 1.0 } } }); // 2. 禁用高级渲染功能 viewer.scene.highDynamicRange = false; viewer.scene.fxaa = false; ``` #### 4. 系统/环境修复 1. **更新显卡驱动**:确保使用最新版本 2. **启用硬件加速**: - Chrome:`设置 > 系统 > 使用硬件加速模式` - Firefox:`选项 > 常规 > 性能 > 使用推荐性能设置` 3. **浏览器更新**:使用最新版 Chrome/Firefox/Edge 4. **清除缓存**:清除浏览器缓存和 WebGL 状态 ### 替代方案 如果问题持续存在,考虑回退到稳定版本: ```bash npm install cesium@1.107 # 使用长期支持版本 ``` ### 调试建议 在浏览器控制台运行: ```javascript // 检查WebGL上下文 const canvas = document.querySelector('canvas'); const gl = canvas.getContext('webgl'); console.log(gl.getShaderInfoLog(gl.createShader(gl.FRAGMENT_SHADER))); // 检查Cesium状态 console.log(Cesium.Context.getNumberOfTextureUnits()); console.log(Cesium.Context.maximumTextureSize); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值