开源GIS相关Gis专辑

等时圈实现

2018-11-23  本文已影响8人  上岸躲雨

等时圈是指从某点出发,以某种交通方式在特定时间内能到达的距离覆盖的范围。前段时间看到一个站点,该站点能够计算自驾、骑行、步行三种方式的等时圈。效果如下图

image

mapbox出品的图还是相当漂亮的,但毕竟是别人的东西,能自己做出来当然是好的(这个功能还是学生的时候就想做)。那就试试呗。

当然先看看mapbox是怎么做的,查看站点使用什么接口,如下图发生数据请求,接口连接

image

对所有接口坐标进行分析,发现所有坐标的分布如下图:

image

从这些点就能猜出mapbox实现思路

image.png

参照这个思路,借助mapbox的接口完全能够自己实现等时圈功能。

  1. 生成网格,使用turf实现,上代码:
var centerPoint = turf.point([116.46, 39.92]);
//生成缓冲区
var buffered = turf.buffer(centerPoint, 12, {units: 'kilometers'});
//根据缓冲区生成bbox
var bbox = turf.bbox(buffered);
var cellSide = 1;
var options = {units: 'kilometers'};
//生成网格
var grid = turf.pointGrid(bbox, cellSide, options);
  1. 利用mapbox接口计算网格各点时间属性。
 /**
     * 
     * @param startPoint
     * @param endPoints
     * @param travelType  walking driving,cycling
     */
function makeRequest(startPoint,endPoints,travelType){
        var url= "https://api.mapbox.com/directions-matrix/v1/mapbox/"+travelType+"/"+startPoint.geometry.coordinates[0].toFixed(4)+","+startPoint.geometry.coordinates[1].toFixed(4)+";"
        if(endPoints.length>0){
            for(var i=0;i<endPoints.length;i++){
                url=url+endPoints[i].geometry.coordinates[0].toFixed(4)+","+endPoints[i].geometry.coordinates[1].toFixed(4)+";";
            }
            url=url+"?sources=0&destinations=all&access_token=pk.eyJ1IjoicGV0ZXJxbGl1IiwiYSI6ImpvZmV0UEEifQ._D4bRmVcGfJvo1wjuOpA1g";
            url=url.replace(";?","?")
            $.ajax({
                type : "get",
                async:false,
                url : url,
                dataType : "json",
                success : function(json){
                    var destinations=json.destinations;
                    var durations=json.durations;
                    for(var i=1;i<destinations.length;i++){
                        var point = turf.point(destinations[i].location,{duration:durations[0][i]});
                        points.push(point)
                    }
                },
                error:function(){
                    console.log('fail');
                }
            });
        }

    }
  1. 生成等值线
    turf有生成等值线的功能
var collections = turf.featureCollection(features);
var breaks = [0, 600,700,800,900, 1200,1500, 1800,2100, 2400,2700, 3000, 3600, 4200, 4800,5400, 6000];
var lines = turf.isolines(collections, breaks, {zProperty: 'duration'});
效果图
看效果,虽然能实现,但是和mapbox效果感觉差了点什么,查看mapbox例子的代码,发现它使用该组件link进行等时线生成。
//它是这么使用的,但是实在看不懂这些参数是个啥意思
var data = [[0, 1, 0], [1, 2, 1], [0, 1, 0]];
var c = new Conrec;
c.contour(data, 0, 2, 0, 2, [1, 2, 3], [1, 2, 3], 3, [0, 1, 2]);

但是貌似这个组件效果是蛮好的。

image
    function getNearestPoint(x,y,pts){
        var ptsjson = turf.featureCollection(pts);
        var targetPoint = turf.point([x, y]);
        var nearest = turf.nearestPoint(targetPoint, ptsjson);
        return  nearest;
    }

//这里为啥要这么写,琢磨了好久,就不解释了
   xs=[];
   ys=[];
   for(var i=0;i<grid.features.length;i++){
        if(xs.indexOf(parseFloat(grid.features[i].geometry.coordinates[0].toFixed(4)))==-1){
            xs.push(parseFloat(grid.features[i].geometry.coordinates[0].toFixed(4)))
        }
    
        if(ys.indexOf(parseFloat(grid.features[i].geometry.coordinates[1].toFixed(4)))==-1){
            ys.push(parseFloat(grid.features[i].geometry.coordinates[1].toFixed(4)))
        }
    }
    var zs = [0,300, 600,900, 1200,1500, 1800,2100, 2400,2700, 3000,3300, 3600,3900, 4200,4500, 4800, 5100,5400, 5700,6000];
    
  var data=[];
   for (var y=0;y<ys.length;y++){
        var rowData=[];
        for (var x=0;x<xs.length;x++){
            var nearest=getNearestPoint(xs[x],ys[y],points)
            temperature=nearest.properties.temperature;
            rowData.push(temperature);
        }
        data.push(rowData)
    }    
        
 var c = new Conrec();
 c.contour(data, 0, xs.length - 1, 0, ys.length - 1, xs, ys, zs.length, zs);
  1. 将等时线连成等时面
 function polygonize(contourList){
        var shapes = []
        var results=[];
        polygons = [];
        for(var cIndex=0;cIndex<contourList.length;cIndex++){
            var c=contourList[cIndex];
            var level=c.level;
            var shape=[];
            for(var k=0;k<c.length;k++){
                shape.push([c[k].x, c[k].y])
            }
            shape.push(shape[0]);
            for (var p = shape.length; p<4; p++){
                shape.push(shape[0]);
            }
            var polygon = turf.polygon([shape], { level: level });
            shapes.push(polygon);
        }
        return shapes;

    }
image
  1. 等时圈生成,并可视化
    使用turf进行处理,将大圈内的小圈叠加掉。
function polygonize(contourList){
        var shapes = []
        var results=[];
        polygons = [];
        for(var cIndex=0;cIndex<contourList.length;cIndex++){
            var c=contourList[cIndex];
            var level=c.level;
            var shape=[];
            for(var k=0;k<c.length;k++){
                shape.push([c[k].x, c[k].y])
            }
            shape.push(shape[0]);
            for (var p = shape.length; p<4; p++){
                shape.push(shape[0]);
            }
            var polygon = turf.polygon([shape], { level: level });
            shapes.push(polygon);
        }
        for(var i=1;i<shapes.length;i++){
            var level=shapes[i].properties.level;
            var difference = turf.difference(shapes[i], shapes[i-1]);
            if(difference!=null){
                difference.properties.level=level;
                results.push(difference);
            }
        }
        return results;
    }
    
image

没有正儿八经的进行可视化,但也能看到和mapbox的效果相差不多。但是这个方案存在一个问题,就是mapbox的接口由于网络问题太不稳定。为了保证稳定性需要自己开发该接口,当然可以使用高德的接口 link

上一篇下一篇

猜你喜欢

热点阅读