Java中关于map地图计算的工具类
程序员文章站
2022-04-15 23:42:05
import java.util.*;/** * 地图计算 * @author simonxue */public class Geohash { public final static String TENCENT_MAP_URL = "https://apis.map.qq.com/ws/place/v1/suggestion"; public final static String TENCENT_MAP_CODE = "腾讯地图提供的key"; privat...
一、地图计算方法
import java.util.*;
/**
* 地图计算
* @author
*/
public class Geohash {
public final static String TENCENT_MAP_URL = "https://apis.map.qq.com/ws/place/v1/suggestion";
public final static String TENCENT_MAP_CODE = "腾讯地图提供的key";
private static int numbits = 6 * 5;
final static char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
final static HashMap<Character, Integer> lookup = new HashMap<Character, Integer>();
static {
int i = 0;
for (char c : digits) {
lookup.put(c, i++);
}
}
public double[] decode(String geohash) {
StringBuilder buffer = new StringBuilder();
for (char c : geohash.toCharArray()) {
int i = lookup.get(c) + 32;
buffer.append(Integer.toString(i, 2).substring(1));
}
BitSet lonset = new BitSet();
BitSet latset = new BitSet();
// even bits
int j = 0;
for (int i = 0; i < numbits * 2; i += 2) {
boolean isSet = false;
if (i < buffer.length()) {
isSet = buffer.charAt(i) == '1';
}
lonset.set(j++, isSet);
}
// odd bits
j = 0;
for (int i = 1; i < numbits * 2; i += 2) {
boolean isSet = false;
if (i < buffer.length()) {
isSet = buffer.charAt(i) == '1';
}
latset.set(j++, isSet);
}
double lon = decode(lonset, -180, 180);
double lat = decode(latset, -90, 90);
return new double[]{lat, lon};
}
private double decode(BitSet bs, double floor, double ceiling) {
double mid = 0;
for (int i = 0; i < bs.length(); i++) {
mid = (floor + ceiling) / 2;
if (bs.get(i)) {
floor = mid;
} else {
ceiling = mid;
}
}
return mid;
}
public String encode(String lat, String lon) {
return encode(Double.parseDouble(lat), Double.parseDouble(lon));
}
public String encode(double lat, double lon) {
BitSet latbits = getBits(lat, -90, 90);
BitSet lonbits = getBits(lon, -180, 180);
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < numbits; i++) {
buffer.append((lonbits.get(i)) ? '1' : '0');
buffer.append((latbits.get(i)) ? '1' : '0');
}
return base32(Long.parseLong(buffer.toString(), 2));
}
private BitSet getBits(double lat, double floor, double ceiling) {
BitSet buffer = new BitSet(numbits);
for (int i = 0; i < numbits; i++) {
double mid = (floor + ceiling) / 2;
if (lat >= mid) {
buffer.set(i);
floor = mid;
} else {
ceiling = mid;
}
}
return buffer;
}
public static String base32(long i) {
char[] buf = new char[65];
int charPos = 64;
boolean negative = (i < 0);
if (!negative) {
i = -i;
}
while (i <= -32) {
buf[charPos--] = digits[(int) (-(i % 32))];
i /= 32;
}
buf[charPos] = digits[(int) (-i)];
if (negative) {
buf[--charPos] = '-';
}
return new String(buf, charPos, (65 - charPos));
}
/*********************** 获取九个的矩形编码 ****************************************/
public static String BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
public static Map<String, String> BORDERS = new HashMap<String, String>();
public static Map<String, String> NEIGHBORS = new HashMap<String, String>();
public static void setMap() {
NEIGHBORS.put("right:even", "bc01fg45238967deuvhjyznpkmstqrwx");
NEIGHBORS.put("left:even", "238967debc01fg45kmstqrwxuvhjyznp");
NEIGHBORS.put("top:even", "p0r21436x8zb9dcf5h7kjnmqesgutwvy");
NEIGHBORS.put("bottom:even", "14365h7k9dcfesgujnmqp0r2twvyx8zb");
NEIGHBORS.put("right:odd", "p0r21436x8zb9dcf5h7kjnmqesgutwvy");
NEIGHBORS.put("left:odd", "14365h7k9dcfesgujnmqp0r2twvyx8zb");
NEIGHBORS.put("top:odd", "bc01fg45238967deuvhjyznpkmstqrwx");
NEIGHBORS.put("bottom:odd", "238967debc01fg45kmstqrwxuvhjyznp");
BORDERS.put("right:even", "bcfguvyz");
BORDERS.put("left:even", "0145hjnp");
BORDERS.put("top:even", "prxz");
BORDERS.put("bottom:even", "028b");
BORDERS.put("right:odd", "prxz");
BORDERS.put("left:odd", "028b");
BORDERS.put("top:odd", "bcfguvyz");
BORDERS.put("bottom:odd", "0145hjnp");
}
/**
* 150 * 获取九个点的矩形编码
* 151 *
* 152 * @param geohash
* 153 * @return
* 154
*/
public String[] getGeoHashExpand(String geohash) {
try {
String geohashTop = calculateAdjacent(geohash, "top");
String geohashBottom = calculateAdjacent(geohash, "bottom");
String geohashRight = calculateAdjacent(geohash, "right");
String geohashLeft = calculateAdjacent(geohash, "left");
String geohashTopLeft = calculateAdjacent(geohashLeft, "top");
String geohashTopRight = calculateAdjacent(geohashRight, "top");
String geohashBottomRight = calculateAdjacent(geohashRight,
"bottom");
String geohashBottomLeft = calculateAdjacent(geohashLeft, "bottom");
String[] expand = {geohash, geohashTop, geohashBottom,
geohashRight, geohashLeft, geohashTopLeft, geohashTopRight,
geohashBottomRight, geohashBottomLeft};
return expand;
} catch (Exception e) {
return null;
}
}
/**
* 分别计算每个点的矩形编码
*
* @param srcHash
* @param dir
* @return
*/
public static String calculateAdjacent(String srcHash, String dir) {
srcHash = srcHash.toLowerCase();
char lastChr = srcHash.charAt(srcHash.length() - 1);
int a = srcHash.length() % 2;
String type = (a > 0) ? "odd" : "even";
String base = srcHash.substring(0, srcHash.length() - 1);
if (BORDERS.get(dir + ":" + type).indexOf(lastChr) != -1) {
base = calculateAdjacent(base, dir);
}
base = base
+ BASE32.toCharArray()[(NEIGHBORS.get(dir + ":" + type)
.indexOf(lastChr))];
return base;
}
// 赤道半径(单位m)
private static final double EARTH_RADIUS = 6371;
/**
* * 转化为弧度(rad)
* *
*/
private static double rad(double d) {
return d * Math.PI / 180.0;
}
/**
* 基于googleMap中的算法得到两经纬度之间的距离,计算精度与谷歌地图的距离精度差不多,相差范围在0.2米以下
*
* @param lon1 第一点的精度
* @param lat1 第一点的纬度
* @param lon2 第二点的精度
* @param lat2 第二点的纬度
* @return 返回的距离,单位m
*/
public double getDistance(double lon1, double lat1, double lon2,
double lat2) {
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lon1) - rad(lon2);
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
+ Math.cos(radLat1) * Math.cos(radLat2)
* Math.pow(Math.sin(b / 2), 2)));
s = s * EARTH_RADIUS;
s = Math.round(s * 1000);
return s;
}
/**
* 筛选出在范围里的经纬度集合
* @param lon 经度
* @param lat 纬度
* @param lonLats 经纬度集合 筛选
* @return
*/
public List<Map<String, Double>> screenLonLat(Double lon, Double lat, List<Map<String, Double>> lonLats) {
if (null == lonLats) {
return null;
}
List<Map<String, Double>> lonLatList = new ArrayList<>();
Geohash geohash = new Geohash();
for (Map<String, Double> lonLat : lonLats) {
Double longitude = lonLat.get("longitude");
Double latitude = lonLat.get("latitude");
Double distance = lonLat.get("distance");
//计算两个经纬度之间距离
double dist = geohash.getDistance(lon, lat, longitude, latitude);
if (dist <= distance) {
lonLat.put("distance", (double) Math.round(dist / 1000 * 10) / 10);
lonLatList.add(lonLat);
}
}
Geohash.sortById(lonLatList);
return lonLatList;
}
/**
* 按照集合id升序排序
*
* @param list
*/
public static void sortById(List<Map<String, Double>> list) {
Collections.sort(list, new Comparator<Map<String, Double>>() {
@Override
public int compare(Map<String, Double> u1, Map<String, Double> u2) {
Double id1 = u1.get("distance");
Double id2 = u2.get("distance");
return id1.compareTo(id2);
}
});
}
/**
* 查询腾讯地图 关键字信息
* @param keyword
* @param region
* @return
*/
@SuppressWarnings("unused")
public static String tencentMapList(String keyword,String region){
Geohash geohash = new Geohash();
StringBuffer stringBuffer = new StringBuffer(TENCENT_MAP_URL);
stringBuffer.append("?").append("region=").append(region).append("&keyword=").
append(keyword).append("&key=").append(TENCENT_MAP_CODE);
return HttpRequestUtils.get(stringBuffer.toString());
}
}
二、查询腾讯地图 关键字信息 上面所需要的HttpRequestUtils工具类
package me.xueyao.http;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
/**
* @Author:
* @Date: Created in 10:26 2019/09/05
*/
@Slf4j
public class HttpRequestUtils {
private static CloseableHttpClient httpClient;
static {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(100);
cm.setDefaultMaxPerRoute(20);
cm.setDefaultMaxPerRoute(50);
httpClient = HttpClients.custom().setConnectionManager(cm).build();
}
public static String get(String url) {
CloseableHttpResponse response = null;
BufferedReader in = null;
String result = "";
try {
HttpGet httpGet = new HttpGet(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
httpGet.setConfig(requestConfig);
httpGet.setConfig(requestConfig);
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
httpGet.setHeader("Accept", "application/json");
response = httpClient.execute(httpGet);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
result = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != response) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
public static String post(String url, String jsonString) {
CloseableHttpResponse response = null;
BufferedReader in = null;
String result = "";
try {
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
httpPost.setConfig(requestConfig);
httpPost.setConfig(requestConfig);
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
httpPost.setHeader("Accept", "application/json");
httpPost.setEntity(new StringEntity(jsonString, Charset.forName("UTF-8")));
response = httpClient.execute(httpPost);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
result = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != response) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("php-x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("x-forwarded-for");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
本文地址:https://blog.csdn.net/JavaWebEngineer/article/details/107332967
下一篇: 荐 Java设计模式(十):外观模式