项目需要用到离线GIS,研究了一下,做个记录
需要百度离线api的js
参考:
于忠达 https://my.oschina.net/smzd/blog/548538
giao00000 https://blog.csdn.net/wml00000/article/details/82219015
第一个是api2.0 第二个是在此基础上的3.0,我用的是2.0
使用起来和在线的差不多,引入api.js就可以,具体看大佬博客吧
另外一个是地图瓦片,因为是离线地图,所以需要把地图资源下载到本地,百度地图背景是一张张的图片,比如放大级别(zoom)是1,是一张最大的图,放大级别为2,地图会被拆成4份,放大级别为3,地图会被拆成16份 ,这样理解。
地图瓦片的坐标是(zoom,x,y)三元素,zoom是缩放级别,X是横坐标,Y是纵坐标,左下角为原点,具体看下图。
比如你想抓15级地图,目测一个矩形区域,找到左下角的一个点,一路放大到需要的级别,看下x,y的范围即可
中国地图15级范围
左下x | 左下y | 右上x | 右上y | |
---|---|---|---|---|
15 | 3825 | 626 | 8614 | 3301 |
网上很多抓取瓦片的工具,不是有水印,就是要收费,所以自己写了个爬虫去爬。
首先一个配置文件,定义级别和范围,存储路径,线程数
config.properties
zIndex=15
left-bottom-x=3825
left-bottom-y=626
right-top-x=8614
right-top-y=3301
thread-size=10
#\u76EE\u5F55\u540E\u9762\u4E0D\u52A0\u659C\u7EBF\u662F\u50BB\u903C
savepath=D:\\work\\tiles\\tiles\\
主进程读取配置信息,启动线程
static
{
Properties pro = new Properties();
try
{
// 开发用这一行 读取当前目录配置文件
// pro.load(Demo1.class.getResourceAsStream("config.properties"));
// 打jar包用这一行 方便外部修改配置文件
pro.load(new FileInputStream("config.properties"));
zIndex = pro.getProperty("zIndex");
savePath = pro.getProperty("savepath");
String leftbottomx = pro.getProperty("left-bottom-x");
String leftbottomy = pro.getProperty("left-bottom-y");
String righttopx = pro.getProperty("right-top-x");
String righttopy = pro.getProperty("right-top-y");
String threadsize = pro.getProperty("thread-size");
xmin = Integer.valueOf(leftbottomx);
ymin = Integer.valueOf(leftbottomy);
xmax = Integer.valueOf(righttopx);
ymax = Integer.valueOf(righttopy);
threadSize = Integer.valueOf(threadsize);
System.out.println("读取数据完成xmin:" + xmin + " ymin:" + ymin + " xmax:"
+ xmax + " ymax:" + ymax);
}
catch (IOException e)
{
e.printStackTrace();
}
}
根据线程数确定每个线程的任务,线程池什么的都没用,直接跑把。。。
private void getImg()
{
// 以x分开多线程
Integer needRunTaskSize = xmax - xmin;
Integer erevtSize = needRunTaskSize / threadSize;
for (int i = 0; i < threadSize; i++)
{
// 算出这个线程的范围
ImgTask imgTask = new ImgTask(zIndex, erevtSize * (i) + xmin,
erevtSize * (i + 1) + xmin, ymin, ymax);
imgTask.setSavePath(savePath);
imgTask.start();
}
int lave = needRunTaskSize % threadSize;
if (lave != 0)
{
// 多跑一个处理剩余的
ImgTask imgTask = new ImgTask(zIndex, xmax - lave, xmax, ymin,
ymax);
imgTask.setSavePath(savePath);
imgTask.start();
}
}
这是个日志文件根据当前任务的范围命名,记录任务状态,下面的都写在了run()里面
File logfile = new File(xmin + "to" + xmax);
BufferedWriter bWriter = null;
if (!logfile.exists())
{
try
{
logfile.createNewFile();
}
catch (IOException e)
{
e.printStackTrace();
}
}
try
{
bWriter = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(logfile, true), "utf-8"));
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
接下来就是根据参数构建url,这个url可以去官网随便找个demo看下最新的网址是什么,udt=20181205这个参数越新,数据也就越新。
先去判断是不是有这个文件了,有的话就不用请求了,比如任务中断了,下次再跑不用把前面的再请求一遍。
String link = "http://online0.map.bdimg.com/tile/?qt=vtile&x={x}&y={y}&z={z}&styles=pl&scaler=1&udt=20181205&xxx={rand}";
for (int i = xmin; i <= xmax; i++)
{ // 循环X
for (int j = ymin; j <= ymax; j++)
{ // 循环Y
try
{
File dir = new File(savePath + z + "/" + i);
if (!dir.exists())
{
dir.mkdirs();
}
File file = new File(
savePath + z + "/" + i + "/" + j + ".png");
// System.out.println(file);
if (!file.exists())
{
file.createNewFile();
}
else
{
bWriter.write("文件存在跳过" + file);
bWriter.newLine();
bWriter.flush();
System.out.println("文件存在跳过" + file);
continue;
}
如果本地没有这个文件,那就下载下来
URL url = new URL(link.replace("{x}", i + "")
.replace("{y}", j + "").replace("{z}", z + "")
.replace("{rand}", new Date().getTime() + ""));
//System.out.println(url);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setConnectTimeout(100);
conn.connect();
InputStream in = conn.getInputStream();
OutputStream out = new FileOutputStream(file);
byte[] bytes = new byte[1024 * 20];
int len = 0;
while ((len = in.read(bytes)) != -1)
{
out.write(bytes, 0, len);
}
out.close();
in.close();
bWriter.write("成功下载" + file);
bWriter.newLine();
bWriter.flush();
然后导出个jar包,放在那里跑把
代码仍在了这里
https://gitee.com/localhost_liangbing/baiduTiles