注意改一下自己的ak
注意修改div的宽高、缩放比例、以及地图中心店经纬度
int width = 500;//地图div宽度
int height = 500;//地图div高度
int zoomLevel = 10;
package com.demo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.net.URL;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
public class BaiduMapDownloadDemo {
public static int calcIdx = 1;
public static int count = 0;
private static String targetDir = "d:\\bMapImg\\beijing"; //下载目标文件夹
private static String sourceDataFile = "d:\\bMapImgNew\\beijingMapData.txt"; //瓦片数据文件
private static ExecutorService threadPool;
private static Double EARTHRADIUS = 6370996.81;
private static Double[] MCBAND = { 12890594.86, 8362377.87, 5591021d,
3481989.83, 1678043.12, 0d };
private static Double[] LLBAND = { 75d, 60d, 45d, 30d, 15d, 0d };
private static Double[][] MC2LL = {
{ 1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331,
200.9824383106796, -187.2403703815547, 91.6087516669843,
-23.38765649603339, 2.57121317296198, -0.03801003308653,
17337981.2 },
{ -7.435856389565537e-9, 0.000008983055097726239,
-0.78625201886289, 96.32687599759846, -1.85204757529826,
-59.36935905485877, 47.40033549296737, -16.50741931063887,
2.28786674699375, 10260144.86 },
{ -3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616,
59.74293618442277, 7.357984074871, -25.38371002664745,
13.45380521110908, -3.29883767235584, 0.32710905363475,
6856817.37 },
{ -1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591,
40.31678527705744, 0.65659298677277, -4.44255534477492,
0.85341911805263, 0.12923347998204, -0.04625736007561,
4482777.06 },
{ 3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062,
23.10934304144901, -0.00023663490511, -0.6321817810242,
-0.00663494467273, 0.03430082397953, -0.00466043876332,
2555164.4 },
{ 2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8,
7.47137025468032, -0.00000353937994, -0.02145144861037,
-0.00001234426596, 0.00010322952773, -0.00000323890364,
826088.5 } };
private static Double[][] LL2MC = {
{ -0.0015702102444, 111320.7020616939, 1704480524535203d,
-10338987376042340d, 26112667856603880d,
-35149669176653700d, 26595700718403920d,
-10725012454188240d, 1800819912950474d, 82.5 },
{ 0.0008277824516172526, 111320.7020463578, 647795574.6671607,
-4082003173.641316, 10774905663.51142, -15171875531.51559,
12053065338.62167, -5124939663.577472, 913311935.9512032,
67.5 },
{ 0.00337398766765, 111320.7020202162, 4481351.045890365,
-23393751.19931662, 79682215.47186455, -115964993.2797253,
97236711.15602145, -43661946.33752821, 8477230.501135234,
52.5 },
{ 0.00220636496208, 111320.7020209128, 51751.86112841131,
3796837.749470245, 992013.7397791013, -1221952.21711287,
1340652.697009075, -620943.6990984312, 144416.9293806241,
37.5 },
{ -0.0003441963504368392, 111320.7020576856, 278.2353980772752,
2485758.690035394, 6070.750963243378, 54821.18345352118,
9540.606633304236, -2710.55326746645, 1405.483844121726,
22.5 },
{ -0.0003218135878613132, 111320.7020701615, 0.00369383431289,
823725.6402795718, 0.46104986909093, 2351.343141331292,
1.58060784298199, 8.77738589078284, 0.37238884252424, 7.45 } };
public static void downloadBaiduMapPic(String dir,String dataFile){
targetDir = dir;
sourceDataFile = dataFile;
threadPool = Executors.newFixedThreadPool(10);
try {
//2019-6-4发现百度地图增加SESSION校验,先获取SESSION
//HttpClientDemo demo = new HttpClientDemo();
String urlLogin = "http://lbsyun.baidu.com/custom/";
DefaultHttpClient client = new DefaultHttpClient(
new PoolingClientConnectionManager());
HttpPost post = new HttpPost(urlLogin);
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
CookieStore cookieStore = client.getCookieStore();
client.setCookieStore(cookieStore);
//遍历数据
LineNumberReader lnr = new LineNumberReader(new FileReader(sourceDataFile));
lnr.skip(Long.MAX_VALUE);
count = lnr.getLineNumber() + 1;
lnr.close();
FileInputStream fileInputStream = new FileInputStream(new File(sourceDataFile));
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String text = null;
while((text = bufferedReader.readLine()) != null){
String[] data = text.split(",");
//包含瓦片样式
String uri = "http://api1.map.bdimg.com/customimage/tile?&x="+data[1]+"&y="+data[2]+"&z="+data[0]+
"&udt=20190425&scale=1&ak=这里改成自己的AK&"
+ "styles=t%3Awater%7Ce%3Aall%7Cc%3A%230E69A7%2Ct%3Ahighway%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Ahighway%7Ce%3Ag.s%7Cc%3A%23147a92%2Ct%3Aarterial%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Alocal"
+ "%7Ce%3Ag%7Cc%3A%23000000%2Ct%3Aland%7Ce%3Aall%7Cc%3A%2308304b%2Ct%3Arailway%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Arailway%7Ce"
+ "%3Ag.s%7Cc%3A%2308304b%2Ct%3Aall%7Ce%3Al.t.f%7Cc%3A%23857f7f%2Ct%3Aall%7Ce%3Al.t.s%7Cc%3A%23000000%2Ct%3Agreen%7Ce%3Ag%7Cc"
+ "%3A%23062032%2Ct%3Aboundary%7Ce%3Aall%7Cc%3A%23AB101C%7Cw%3A1.5%2Ct%3Aall%7Ce%3Al.i%7Cv%3Aoff%2Ct%3Aall%7Ce%3Al.t.f%7Cv"
+ "%3Aon%7Cc%3A%232da0c6%2Ct%3Aroad%7Ce%3Al.t.f%7Cv%3Aoff%7Cc%3A%232da0c6";
//String uri = "http://api1.map.bdimg.com/customimage/tile?&x="+data[1]+"&y="+data[2]+"&z="+data[0]+"&udt=20171128&scale=1&ak=offlinekey&customid=midnight";
HttpGet get = new HttpGet(uri);
get.addHeader("Accept","image/webp,image/*,*/*;q=0.8");
get.addHeader("Accept-Encoding","gzip, deflate, sdch");
get.addHeader("Accept-Language","zh-CN,zh;q=0.8");
get.addHeader("Cache-Control","no-cache");
get.addHeader("Connection","keep-alive");
get.addHeader("Host","api1.map.bdimg.com");
get.addHeader("Pragma","no-cache");
get.addHeader("Referer","http://lbsyun.baidu.com/custom/");
get.addHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36");
DownLoadThread t = new DownLoadThread(data[1], ""+Math.abs(Integer.parseInt(data[2])), data[0], targetDir,
get,response,client);
threadPool.execute(t);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public static void main(String[] args) {
//获取瓦片
BaiduMapDownloadDemo.downloadBaiduMapPic("F:\\bMapImg3\\beijing", "F:\\bMapImgNew\\333.txt");
//计算瓦片,将计算出的瓦片地址放入333.txt中
Map<String, Double> location = convertMC2LL(13372307.47, 3514145.00);
location = convertLL2MC(location.get("lng"),location.get("lat"));
System.out.println(location);
int width = 500;//地图div宽度
int height = 500;//地图div高度
int zoomLevel = 10;
Map<String, Double> centerLL = new HashMap<String, Double>();
centerLL.put("lng", 116.3964D);
centerLL.put("lat", 39.9093D);
Map<String, Double> center = convertLL2MC(centerLL.get("lng"),centerLL.get("lat"));
System.out.println(location);
double cV = Math.pow(2, 18-zoomLevel);//现在直接计算这个数。理论不变,代码变了,我们直接计算好了。
double unitSize = cV * 256; //这个也只能自己计算了//mapType.getZoomFactor(zoomLevel);// 一个系数,=cV*256
double longitudeUnits = Math.ceil(center.get("x") / unitSize);// center.lng是一个很大的数
double latitudeUnits = Math.ceil(center.get("y") / unitSize);//这两个不用解释了吧
double tileSize = 256; //这个直接给常亮吧。要不得是mapType.k.Ob//mapType.getTileSize();
double[] cP = new double[]{ longitudeUnits,
latitudeUnits,
(center.get("x") - longitudeUnits * unitSize) / unitSize * tileSize,
(center.get("y") - latitudeUnits * unitSize) / unitSize * tileSize };
double left = (cP[0] - Math.ceil((width / 2 - cP[2]) / tileSize));
double top = (cP[1] - Math.ceil((height / 2 - cP[3]) / tileSize));
double right = (cP[0] + Math.ceil((width / 2 + cP[2]) / tileSize));
double c0 = 0;
//if (mapType === BMAP_PERSPECTIVE_MAP && map.getZoom() == 15) {//这句应该不起作用
// c0 = 1
//}
double bottom = (cP[1] + Math.ceil((height / 2 + cP[3]) / tileSize) + c0);
List<String> xydata = new ArrayList<String>();
for (double i = left; i < right; i++) {
for (double j = top; j < bottom; j++) {
System.out.println(zoomLevel+","+(int)i+","+ (int)j);
xydata.add(zoomLevel+","+(int)i+","+ (int)j);
}
}
//这个地方能直接获取瓦片地址的内部方法,挺好,省去了很多的代码移植。
// var getTilesUrl = map.getMapType().getTileLayer().getTilesUrl;
// //循环获取代码吧
// for (var i = 0, len = xydata.length; i < len; i++) {
// var url = getTilesUrl({x:xydata[i][0],y:xydata[i][1]}, zoomLevel, "normal");
// var path = zoomLevel+"/"+xydata[i][0]+"/"+xydata[i][1]+".png";
// if(!!callback){
// callback(path, url);
// }
// }
// 根据百度经纬度计算出来墨卡托坐标后,将结果除以地图分辨率Math.Pow(2,18-zoom)即可得到平面像素坐标,然后将像素坐标除以256分别得到瓦片的行列号。
//
// String geo = "4|12928784.8679,4580889.0672;12928884.0335,4581026.05389|1-12928784.8679,4581018.53244,12928879.8193,4581026.05389,12928884.0335,4580966.20191,12928847.7346,4580961.14681,12928844.1937,4580957.53999,12928850.7314,4580891.67584,12928791.9678,4580889.0672,12928784.8679,4581018.53244;";
// List<String> mocatorList = parseJeo(geo);
// StringBuilder sb = new StringBuilder();
// for (int i = 0; i < mocatorList.size(); i++) {
// String[] coordinate = mocatorList.get(i).split("\\#");
// Map<String, Double> location = convertMC2LL(
// Double.parseDouble(coordinate[0]),
// Double.parseDouble(coordinate[1]));
// Double lng = location.get("lng");
// Double lat = location.get("lat");
// String coord = lng + "," + lat;
// sb.append(coord);
// if (i < mocatorList.size() - 1) {
// sb.append(";");
// }
// }
// System.out.println(sb.toString());
}
/**
* 解析Jeo数据
*
* @param mocator
*/
public static List<String> parseJeo(String mocator) {
List<String> mocatorList = new ArrayList<String>();
if (null == mocator)
return null;
/* 拆分数据 */
String[] geos = mocator.split("\\|");
int n = Integer.parseInt(geos[0]);
String center = geos[1];
String polylineMoca = geos[2]; // 墨卡托坐标
String[] plm = polylineMoca.split("\\;");
/* 获取墨卡托边界 */
String geo = null;
if (n == 4) {
for (int i = 0; i < plm.length; i++) {
String[] geoPaths = plm[i].split("\\-");
if (geoPaths[0].equals("1")) {
geo = geoPaths[1];
}
}
}
// 墨卡托坐标解析
String[] geoPolyline = geo.split("\\,");
for (int i = 0; i < geoPolyline.length; i += 2) {
mocatorList.add(geoPolyline[i] + "#" + geoPolyline[i + 1]);
}
return mocatorList;
}
/**
* 墨卡托坐标转经纬度坐标
*
* @param x
* @param y
* @return
*/
public static Map<String, Double> convertMC2LL(Double x, Double y) {
Double[] cF = null;
x = Math.abs(x);
y = Math.abs(y);
for (int cE = 0; cE < MCBAND.length; cE++) {
if (y >= MCBAND[cE]) {
cF = MC2LL[cE];
break;
}
}
Map<String, Double> location = converter(x, y, cF);
location.put("lng", location.get("x"));
location.remove("x");
location.put("lat", location.get("y"));
location.remove("y");
return location;
}
/**
* 经纬度坐标转墨卡托坐标
*
* @param lng
* @param lat
* @return
*/
public static Map<String, Double> convertLL2MC(Double lng, Double lat) {
Double[] cE = null;
lng = getLoop(lng, -180, 180);
lat = getRange(lat, -74, 74);
for (int i = 0; i < LLBAND.length; i++) {
if (lat >= LLBAND[i]) {
cE = LL2MC[i];
break;
}
}
if (cE != null) {
for (int i = LLBAND.length - 1; i >= 0; i--) {
if (lat <= -LLBAND[i]) {
cE = LL2MC[i];
break;
}
}
}
return converter(lng, lat, cE);
}
private static Map<String, Double> converter(Double x, Double y, Double[] cE) {
Double xTemp = cE[0] + cE[1] * Math.abs(x);
Double cC = Math.abs(y) / cE[9];
Double yTemp = cE[2] + cE[3] * cC + cE[4] * cC * cC + cE[5] * cC * cC
* cC + cE[6] * cC * cC * cC * cC + cE[7] * cC * cC * cC * cC
* cC + cE[8] * cC * cC * cC * cC * cC * cC;
xTemp *= (x < 0 ? -1 : 1);
yTemp *= (y < 0 ? -1 : 1);
Map<String, Double> location = new HashMap<String, Double>();
location.put("x", xTemp);
location.put("y", yTemp);
return location;
}
private static Double getLoop(Double lng, Integer min, Integer max) {
while (lng > max) {
lng -= max - min;
}
while (lng < min) {
lng += max - min;
}
return lng;
}
private static Double getRange(Double lat, Integer min, Integer max) {
if (min != null) {
lat = Math.max(lat, min);
}
if (max != null) {
lat = Math.min(lat, max);
}
return lat;
}
public static void collectMapData(String sourceDir,String targetFile){
try{
File rootFile = new File(sourceDir);
File[] zFiles = rootFile.listFiles();
for(File zFile :zFiles){
String zName = "";
if(zFile.isDirectory()){
zName = zFile.getName();
File[] xFiles = zFile.listFiles();
for(File xFile:xFiles){
String xName = xFile.getName();
File[] yFiles = xFile.listFiles();
for(File yFile:yFiles){
String yName = yFile.getName();
yName = yName.substring(0,yName.indexOf("."));
appendTofile(targetFile,zName+","+xName+","+yName);
}
}
}
}
}catch(Exception e){
e.printStackTrace();
}
}
private static void appendTofile(String targetFile,String content) {
FileWriter fw = null;
try {
File f = new File(targetFile);
fw = new FileWriter(f, true);
} catch (Exception e) {
e.printStackTrace();
}
PrintWriter pw = new PrintWriter(fw);
pw.println(content);
pw.flush();
try {
fw.flush();
pw.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void writeToFile(File file,String content){
try {
if(file.exists()){
FileWriter fw = new FileWriter(file,true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
fw.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class DownLoadThread implements Runnable{
private String x;
private String y;
private String z;
private String targetDir;
private HttpGet get;
private HttpResponse response;
private DefaultHttpClient client;
DownLoadThread(String x,String y,String z,String targetDir,HttpGet get,HttpResponse response,DefaultHttpClient
client){
this.x = x;
this.y = y;
this.z = z;
this.targetDir = targetDir;
this.get = get;
this.response = response;
this.client = client;
}
@Override
public void run() {
DataInputStream dataInputStream = null;
FileOutputStream fileOutputStream = null;
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMinimumFractionDigits(2);
try {
HttpEntity entity = response.getEntity();
response = client.execute(get);
entity = response.getEntity();
dataInputStream = new DataInputStream(entity.getContent());
//检查文件夹是否存在
File zFile = new File(targetDir+"\\"+z);
if(!zFile.exists()){
zFile.mkdir();
}
File xFile = new File(targetDir+"\\"+z+"\\"+x);
if(!xFile.exists()){
xFile.mkdir();
}
String imageName = targetDir+"\\"+z+"\\"+x+"\\"+y+".png";
fileOutputStream = new FileOutputStream(new File(imageName));
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = dataInputStream.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
output.close();
System.out.println("已完成:"+BaiduMapDownloadDemo.calcIdx+"/"+BaiduMapDownloadDemo.count+"("+nf.format((BaiduMapDownloadDemo.calcIdx/(BaiduMapDownloadDemo.count*1.0))*100)+"%)");
BaiduMapDownloadDemo.calcIdx++;
}catch (Exception e) {
e.printStackTrace();
}
}
}