百度瓦片地图制作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013415591/article/details/77541109

在网上查询了很久,找了很多百度瓦片地图下载文章,但是并没有我想要如何下载百度地图操作的文章教程。通过同事指点加自我摸索理解,总结如下关于下载百度瓦片地图制作的教程。

我们下载某个地区的地图,首先我们需要获取 图块坐标

百度地图API在展示地图时是将整个地图图片切割成若干图块来显示的,当地图初始化或是地图级别、中心点位置发生变化时,地图API会根据当前像素坐标计算出视野内需要的图块坐标(也叫图块编号),从而加载对应的图块用以显示地图。
百度地图的图块坐标原点与平面坐标一致,从原点向右上方开始编号为0, 0:
这里写图片描述
如何知道某个位置的图块坐标呢?通过如下公式计算即可(这里为向下取整):
图块坐标 =|像素坐标 ÷ 256|
256实际上是每个图块的宽度和高度,我们用像素坐标除以这个数就知道图块坐标了。还以天安门为例,在第4级下天安门所在的图块编号为:3, 1,而在第18级下,图块编号为:50617, 18851

如何获取百度图块坐标?
打开百度开发平台:http://lbsyun.baidu.com/jsdemo.htm?a#i7_1
将如下代码放入编辑器运行:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>地图坐标概念</title>
<script src="http://api.map.baidu.com/api?v=1.2"></script>
</head>
<body>
<div id="map_container" style="width:500px;height:320px;"></div>
<script>
var map =new BMap.Map('map_container', {defaultCursor: 'default'});
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);

var TILE_SIZE =256;

map.addEventListener('click', function(e){
var info =new BMap.InfoWindow('', {width: 260});
var projection =this.getMapType().getProjection();

var lngLat = e.point; 
var lngLatStr ="经纬度:"+ lngLat.lng +", "+ lngLat.lat;

var worldCoordinate = projection.lngLatToPoint(lngLat);
var worldCoordStr ="<br />平面坐标:"+ worldCoordinate.x +", "+ worldCoordinate.y;

var pixelCoordinate =new BMap.Pixel(Math.floor(worldCoordinate.x * Math.pow(2, this.getZoom() -18)), 
Math.floor(worldCoordinate.y * Math.pow(2, this.getZoom() -18)));
var pixelCoordStr ="<br />像素坐标:"+ pixelCoordinate.x +", "+ pixelCoordinate.y;

var tileCoordinate =new BMap.Pixel(Math.floor(pixelCoordinate.x /256),
Math.floor(pixelCoordinate.y /256));
var tileCoordStr ="<br />图块坐标:"+ tileCoordinate.x +", "+ tileCoordinate.y;

var viewportCoordinate = map.pointToPixel(lngLat);
var viewportCoordStr ="<br />可视区域坐标:"+ viewportCoordinate.x +", "+ viewportCoordinate.y;

var overlayCoordinate = map.pointToOverlayPixel(lngLat);
var overlayCoordStr ="<br />覆盖物坐标:"+ overlayCoordinate.x +", "+ overlayCoordinate.y;

info.setContent(lngLatStr + worldCoordStr + pixelCoordStr + tileCoordStr + 
viewportCoordStr + overlayCoordStr);
map.openInfoWindow(info, lngLat);
});
</script>
</body>
</html>

运行出来之后点击地图上会出现如图:
这里写图片描述
如此可以轻松地获取图块坐标信息。

如何下载百度瓦片?
通过上述可以轻松获取到地域图块坐标范围值。
提供如下Java代码下载瓦片图片:

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * <pre>
 * 参考资料:
 * <a href="http://www.jianshu.com/p/0b292688b6af">国内主要地图瓦片坐标系定义及计算原理</a>
 * <a href="http://www.cnblogs.com/xiaozhi_5638/p/4748186.html">百度地图根据经纬度计算瓦片行列号</a>
 *
 */
public class R implements Runnable {

    static int succeed = 0;
    static int error = 0;
    static int finishedThread = 0;
    static long endTime = 0;
    static String sPath = "http://online1.map.bdimg.com/onlinelabel/?qt=tile&x=%d&y=%d&z=%d&styles=pl&udt=20150924&scaler=1";
    /**
    * z : 层级
    * xstart : x的开始值
    * xend  : x的最大值
    * ystart  : y的开始值
    * yend  : y的最大值
    * threads : 几个线程开始下载地图 
    */
    int z=11, xstart = 407,xend = 409,ystart = 113,yend = 116,threads = 1;
    //下载瓦片地图存放地址
    String dir = ""; 
    //是否覆盖之前下载的图片
    boolean overwrite = false; 

    Map<String, String> map = Maps.newHashMap();
    public R(Map<String, String> map) {
        this.map = map;
    }

    public static void main(String[] args) {

        final Map<String, String> map = Maps.newHashMap();

        /*Lists.newArrayList(args).forEach(s -> {
            String k = s.split("=")[0];
            String v = s.split("=")[1];
            map.put(k, v);
        });*/
        List<String> list = Lists.newArrayList(args);
        for(String str : list){
            String k = str.split("=")[0];
            String v = str.split("=")[1];
            map.put(k, v);
        }
        new R(map).run();

    }

    public void run() {
        ExecutorService exec = Executors.newCachedThreadPool();

        Set<Point> set = Sets.newHashSet();

        int total = (xend - xstart) * (yend - ystart);

        int split = total / threads;
        int count = 0;
        for(int i=xstart;i<=xend;i++) {
            for(int j=ystart;j<yend;j++) {
                set.add(new Point(i, j));
                if(++count % split == 0) {
                    exec.execute(new DownloadThread(set));
                    set = Sets.newHashSet();
                }
            }
        }
        if(set.size()>0) {
            exec.execute(new DownloadThread(set));
        }

        long t = System.currentTimeMillis();
        while (finishedThread < threads) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println("耗时 " + (System.currentTimeMillis() - t) / 1000 + "s 成功 " + succeed + " 失败 " + error + " ok="+finishedThread+" total = "+total);
        }
        exec.shutdown();
        System.out.println("完成 共耗时 " + (endTime - t) / 1000 + "s 成功 " + succeed + " 失败 " + error + " ok="+finishedThread+" total = "+total);
    }

    class DownloadThread extends Thread {
        Set<Point> set;
        public DownloadThread(Set<Point> set) {
            this.set = set;
        }

        public void run() {
            System.out.println(getName() + " started, task size = " + set.size());
            File base = new File(dir, z + "");

            for(Point point : set) {
                int x = point.x;
                int y = point.y;
                File path = new File(base, x + "");
                if (!path.exists()) {
                    path.mkdirs();
                }
                File file = new File(path, y + ".jpg");
                if (!file.exists() || overwrite) {
                    String url = String.format(sPath, x, y, z);
                    boolean b = save(url, file);
                    if (b) {
                        succeed++;
                        System.out.println(file.getAbsolutePath());
                    } else {
                        error++;
                    }
                }
            }
            System.out.println(getName()+" finished");
            finishedThread++;
            endTime = System.currentTimeMillis();
        }

        byte[] b = new byte[4096];
        int s = 0;

        boolean save(String path, File file) {
            InputStream is = null;
            OutputStream os = null;
            try {
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.connect();
                is = conn.getInputStream();
                os = new FileOutputStream(file);
                while ((s = is.read(b)) != -1) {
                    os.write(b, 0, s);
                }
                return true;
            } catch (Exception e) {
                return false;
            } finally {
                if (os != null) {
                    try {
                        os.flush();
                        os.close();
                    } catch (Exception e) {
                    }
                }
                if (is != null) {
                    try {
                        is.close();
                    } catch (Exception e) {
                    }
                }
            }
        }
    }

    static class Point {
        int x, y;
        Point(int x,int y){
            this.x = x;
            this.y = y;
        }
    }
}

通过上述java代码,修改其中参数值,百度瓦片地图下载到指定路径下。

猜你喜欢

转载自blog.csdn.net/u013415591/article/details/77541109