package com.doumee.core.utils;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.TypeReference;
|
import com.doumee.dao.business.web.request.LocaltionDTO;
|
|
import java.awt.geom.GeneralPath;
|
import java.awt.geom.Point2D;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
/**
|
* 计算距离
|
*/
|
public class PositionUtil {
|
|
public static String getTxMapAddrByLatAndLng(Double lat,Double lng,String host,String mapkey){
|
try {
|
if(lat == null || lng ==null){
|
return null;
|
}
|
String url =host +"/ws/geocoder/v1/?key="+mapkey+"&location="+lat+","+lng;
|
String res = HttpsUtil.get(url,false);
|
JSONObject jsonObject = JSONObject.parseObject(res );
|
String r = null;
|
if(jsonObject.getJSONObject("result")!=null){
|
if(jsonObject.getJSONObject("result").getJSONObject("formatted_addresses")!=null){
|
r =jsonObject.getJSONObject("result").getJSONObject("formatted_addresses").getString("formatted_addresses");
|
}
|
if(r!=null && !r.equals("")){
|
r =jsonObject.getJSONObject("result").getString("address");
|
}
|
}
|
return r;
|
|
}catch (Exception e){
|
e.printStackTrace();
|
}
|
return null;
|
}
|
/**
|
* 椭球参数
|
*/
|
private static double pi = 3.14159265358979324;
|
/**
|
* 卫星椭球坐标投影到平面地图坐标系的投影因子
|
*/
|
private static double a = 6378245.0;
|
/**
|
* 椭球的偏心率
|
*/
|
private static double ee = 0.00669342162296594323;
|
|
/**
|
* 经纬度 GPS转高德
|
*
|
* @param wgLon GPS经度
|
* @param wgLat GPS维度
|
* @return 转化后的经纬度坐标
|
*/
|
public static AMap transform(double wgLon, double wgLat) {
|
if (outOfChina(wgLat, wgLon)) {
|
return new AMap(wgLon, wgLat);
|
}
|
|
double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
|
double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
|
double radLat = wgLat / 180.0 * pi;
|
double magic = Math.sin(radLat);
|
magic = 1 - ee * magic * magic;
|
double sqrtMagic = Math.sqrt(magic);
|
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
|
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
|
double transLat = wgLat + dLat;
|
double transLon = wgLon + dLon;
|
return new AMap(transLon, transLat);
|
}
|
|
/**
|
* 判断是否为国外坐标,,不在国内不做偏移
|
*
|
* @param lat
|
* @param lon
|
* @return
|
*/
|
private static Boolean outOfChina(double lat, double lon) {
|
if (lon < 72.004 || lon > 137.8347)
|
return true;
|
if (lat < 0.8293 || lat > 55.8271)
|
return true;
|
return false;
|
}
|
|
/**
|
* 纬度转换
|
*
|
* @param x
|
* @param y
|
* @return
|
*/
|
private static double transformLat(double x, double y) {
|
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
|
ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
|
ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
|
return ret;
|
}
|
|
/**
|
* 经度转换
|
*
|
* @param x
|
* @param y
|
* @return
|
*/
|
private static double transformLon(double x, double y) {
|
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
|
ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
|
ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;
|
return ret;
|
}
|
|
/**
|
* 高德经纬度类
|
*/
|
public static class AMap {
|
/**
|
* 经度
|
*/
|
private double longitude;
|
|
/**
|
* 维度
|
*/
|
private double latitude;
|
|
public AMap(double longitude, double latitude) {
|
this.longitude = longitude;
|
this.latitude = latitude;
|
}
|
|
public double getLongitude() {
|
return longitude;
|
}
|
|
public double getLatitude() {
|
return latitude;
|
}
|
}
|
public static void main(String[] args) {
|
String str ="[{\"lat\": 31.71383446224521, \"lng\": 117.39342857107226, \"height\": 0}, " +
|
"{\"lat\": 31.71393087373135, \"lng\": 117.39402357524818, \"height\": 0}, " +
|
"{\"lat\": 31.713593433089077, \"lng\": 117.39433170240886, \"height\": 0}," +
|
" {\"lat\": 31.713280450806966, \"lng\": 117.39358710879355, \"height\": 0}]";
|
TypeReference typeReference = new TypeReference<List<LocaltionDTO>>(){};
|
List<LocaltionDTO> array = JSONObject.parseObject(str, typeReference.getType());
|
if(array == null || array.size() ==0){
|
System.out.println("=================");
|
}
|
System.out.println(isInPolygon( 117.393962,31.713690,array));
|
AMap aMap = transform( 117.38823300, 31.71550000);
|
System.out.println(aMap.getLatitude()+""+aMap.getLongitude());
|
System.out.println(isInPolygon( aMap.getLongitude(),aMap.getLatitude(),array));
|
}
|
/* "latitude": 31.71553300,
|
"longitude": 117.39,
|
117.393962,31.713690
|
31.71550000 117.38823300
|
*/ /**
|
* 判断坐标点是否在多边形区域内
|
*
|
* @param pointLon 要判断的点的经度
|
* @param pointLat 要判断的点的纬度
|
* @return true:范围内; false:范围外
|
*/
|
public static boolean isInPolygon(double pointLon, double pointLat, List<LocaltionDTO> list) {
|
if(list==null ||list.size()==0){
|
return false;
|
}
|
double[] lon = new double[list.size()];
|
double[] lat = new double[list.size()];
|
for (int i = 0; i < list.size(); i++) {
|
lon[i] = list.get(i).getLng() ==null?0:list.get(i).getLng();
|
lat[i] = list.get(i).getLat() ==null?0:list.get(i).getLat();
|
}
|
// 将要判断的横纵坐标组成一个点
|
Point2D.Double point = new Point2D.Double(pointLon, pointLat);
|
// 将区域各顶点的横纵坐标放到一个点集合里面
|
List<Point2D.Double> pointList = new ArrayList<>();
|
double polygonPointToX;
|
double polygonPointToY;
|
for (int i = 0; i < lon.length; i++) {
|
polygonPointToX = lon[i];
|
polygonPointToY = lat[i];
|
Point2D.Double polygonPoint = new Point2D.Double(polygonPointToX, polygonPointToY);
|
pointList.add(polygonPoint);
|
}
|
return check(point, pointList);
|
}
|
|
/**
|
* 坐标点是否在多边形内
|
*
|
* @param point 要判断的点的横纵坐标
|
* @param polygon 组成的顶点坐标集合
|
*/
|
private static boolean check(Point2D.Double point, List<Point2D.Double> polygon) {
|
GeneralPath generalPath = new GeneralPath();
|
|
Point2D.Double first = polygon.get(0);
|
// 通过移动到指定坐标(以双精度指定),将一个点添加到路径中
|
generalPath.moveTo(first.x, first.y);
|
polygon.remove(0);
|
for (Point2D.Double d : polygon) {
|
// 通过绘制一条从当前坐标到新指定坐标(以双精度指定)的直线,将一个点添加到路径中。
|
generalPath.lineTo(d.x, d.y);
|
}
|
// 将几何多边形封闭
|
generalPath.lineTo(first.x, first.y);
|
generalPath.closePath();
|
// 测试指定的 Point2D 是否在 Shape 的边界内。
|
return generalPath.contains(point);
|
}
|
|
}
|