等时圈实现

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350