前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Ol4网格生成以及优化

Ol4网格生成以及优化

作者头像
lzugis
发布2019-11-14 17:03:57
4350
发布2019-11-14 17:03:57
举报

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://cloud.tencent.com/developer/article/1539120

概述

先描述一下大致场景:以0.05为单元格大小生成网格,并在地图上绘制,绘制的时候需要区分海陆。本文以此需求为契机,简单描述一下该需求的实现以及如何来优化。

效果

实现

优化前

代码语言:javascript
复制
  var source = new ol.source.Vector({
    features: []
  });
  var vector = new ol.layer.Vector({
    source: source,
    zIndex: 1,
    opacity: 0.65,
    style: styleFunction
  });
  map.addLayer(vector);

  var landData = format.readFeatures(chinaZone, options);
  landGeom = landData[0].getGeometry();
  
  function styleFunction(feat) {
    var i = feat.get("i"),
      j = feat.get("j"),
      isLand = feat.get("land");
    if(isLand) {
      var val = data[i][j];
      var color;
      if (val > 0.33 && val <= 0.66) {
        color = "orange";
      } else if (val > 0.66 && val <= 1) {
        color = "red";
      } else {
        color = 'yellow';
      }
      return new ol.style.Style({
        fill: new ol.style.Fill({
          color: color,
        })
      })
    }
  }

  function generateGrid() {
    var bound = $("#bound").val(),
      size = Number($("#size").val());
    var bounds = bound.split(",").map(Number);
    console.time('Time Test');
    createGrid(bounds, size);
    console.timeEnd('Time Test')
  }
  
  function isOnLand(coord) {
    var is = false;
    for(var i = 0;i<landData.length;i++){
      var geom = landData[i].getGeometry();
      if (geom.intersectsCoordinate(coord)) {
        is = true;
        break;
      }
    }
    return is;
  }

  function createGrid(bound, size) {
    var gridData = {
      type: "FeatureCollection",
      features: []
    };
    var deltaLon = bound[2] - bound[0],
      deltaLat = bound[3] - bound[1];
    var numLon, numLat;
    numLon = Math.ceil(deltaLon / size);
    numLat = Math.ceil(deltaLat/ size);
    var minLon = bound[0],
      maxLat = bound[3];
    for(var i = 0; i < numLat; i++) {
      var lat1 = maxLat - i * size,
        lat2 = maxLat - (i + 1) * size;
      var latC = (lat1 + lat2) / 2;
      data[i] = [];
      for(var j = 0; j < numLon; j++) {
        data[i][j] = Math.random();
        var lon1 = minLon + j * size,
          lon2 = minLon + (j + 1) * size;
        var lonC = (lon1 + lon2) / 2;
        var coord = ol.proj.fromLonLat([lonC, latC]);
        var prop = {
          i: i,
          j: j,
          land: isOnLand(coord)
        };
        // 网格面
        var featG = {
          "type":"Feature",
          "properties": prop,
          "geometry":{
            "type":"Polygon",
            "coordinates":[[
              [lon1, lat1],
              [lon2, lat1],
              [lon2, lat2],
              [lon1, lat2],
              [lon1, lat1]
            ]]
          }
        };
        gridData.features.push(featG);
      }
    }
    var gridFeatures = format.readFeatures(gridData, options);
    source.addFeatures(gridFeatures);
  }

优化后

代码语言:javascript
复制
  var source = new ol.source.Vector({
    features: []
  });
  var vector = new ol.layer.Vector({
    source: source,
    zIndex: 1,
    opacity: 0.65,
    style: styleFunction,
    renderMode: 'image'
  });
  map.addLayer(vector);

  var landData = format.readFeatures(chinaZone, options);
  landGeom = landData[0].getGeometry();

  function styleFunction(feat) {
    // i为lat,j为lon
    var i = feat.get("i"),
      j = feat.get("j"),
      land = feat.get("land");
    if(land) {
      var val = data[i][j];
      var color;
      if (val > 0.33 && val <= 0.66) {
        color = "orange";
      } else if (val > 0.66 && val <= 1) {
        color = "red";
      } else {
        color = 'yellow';
      }
      return new ol.style.Style({
        // stroke: new ol.style.Stroke({
        //   color: 'grey',
        //   width: 1
        // }),
        fill: new ol.style.Fill({
          color: color,
        })
      })
    }
  }

  function generateGrid() {
    var bound = $("#bound").val(),
      size = Number($("#size").val());
    var bounds = bound.split(",").map(Number);
    console.time('Time Test');
    createGrid(bounds, size);
    console.timeEnd('Time Test')
  }

  function isOnLand(coord) {
    return landGeom.intersectsCoordinate(coord);
  }

  /**
   * 创建网格
   * @param bound
   * @param size
   * @returns {{grid: {features: Array, type: string}, center: {features: Array, type: string}}}
   */
  function createGrid(bound, size) {
    var deltaLon = bound[2] - bound[0],
      deltaLat = bound[3] - bound[1];
    var numLat;
    numLat = Math.ceil(deltaLat / size);
    for (var i = 0; i < numLat; i++) {
      data[i] = [];
      getFeatures(bound, i, deltaLon, size)
        .then(res => {
          var json = {
            "type": "FeatureCollection",
            features: res
          };
          var features = format.readFeatures(json, options);
          source.addFeatures(features);
        })
    }
  }

  function getFeatures(bound, i, deltaLon, size) {
    var promise = new Promise(function(resolve, reject) {
      window.setTimeout(function() {
        var features = [];
        var minLon = bound[0],
          maxLat = bound[3],
          numLon = Math.ceil(deltaLon / size);

        var lat1 = maxLat - i * size,
          lat2 = maxLat - (i + 1) * size;
        var latC = (lat1 + lat2) / 2;
        for(var j = 0; j < numLon; j++) {
          var lon1 = minLon + j * size,
            lon2 = minLon + (j + 1) * size;
          var lonC = (lon1 + lon2) / 2;
          var coord = ol.proj.fromLonLat([lonC, latC]);
          var prop = {
            i: i,
            j: j,
            land: isOnLand(coord)
          };
          data[i][j] = Math.random();
          // 网格面
          var featG = {
            "type":"Feature",
            "properties": prop,
            "geometry":{
              "type":"Polygon",
              "coordinates":[[
                [lon1, lat1],
                [lon2, lat1],
                [lon2, lat2],
                [lon1, lat2],
                [lon1, lat1]
              ]]
            }
          };
          features.push(featG);
        }
        resolve(features);
      });
    });
    return promise;
  }

思路分析

通过前面的两张图可以明显看出,优化前后效率上有了质的变化,这说明我们的优化思路是正确的。下面说一下我在做这部分优化的时候的思路:

1.找到原因

从本案例来看,能影响效率的有可能有两点:1、js的for循环比较慢;2、渲染到地图上的时候比较慢。于是就做了一下测试,发现原因其实是1,而不是2.

2.思考解决

既然找到了是1影响了效率,那就考虑如何优化1。在本案例中,第一层循环有200,第二层循环有140,由于js的执行是单线程顺序执行的,所以我思考把这个循环拆开,拆成若干个循环,异步执行,这样就能避免同步执行慢的问题。因此,在优化的时候用了setTimeoutpromise来实现循环的异步执行。

3. 其他

此外,在创建vectorLayer的时候,加入了renderMode: 'image'参数,提高渲染层面的效率。

思考优化

本案例其实还可以做进一步的优化,优化主要在渲染上,优化思路类似于地图切片,将展示数据建立索引,并将展示结果进行分块,以达到优化展示。


技术博客

CSDN:http://blog.csdn.NET/gisshixisheng

在线教程

https://edu.csdn.net/course/detail/799

https://edu.csdn.net/course/detail/7471

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 效果
  • 实现
    • 优化前
      • 优化后
      • 思路分析
        • 1.找到原因
          • 2.思考解决
            • 3. 其他
            • 思考优化
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档