地球坐标系、火星坐标系等相互转换、判断点是否在区域内(经纬度)工具类
1、坐标系种类简介
- WGS84坐标系
即地球坐标系,国际上通用的坐标系。
设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系。谷歌地图采用的是WGS84地理坐标系(中国范围除外,谷歌中国地图采用的是GCJ02地理坐标系。) - GCJ02坐标系
即火星坐标系,WGS84坐标系经加密后的坐标系。
出于国家安全考虑,国内所有导航电子地图必须使用国家测绘局制定的加密坐标系统,即将一个真实的经纬度坐标加密成一个不正确的经纬度坐标。 - BD09坐标系
即百度坐标系,GCJ02坐标系经加密后的坐标系。搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。 - 各主流地图API采用的坐标系
高德MapABC地图API 火星坐标
腾讯搜搜地图API 火星坐标
阿里云地图API 火星坐标
灵图51ditu地图API 火星坐标
百度地图API 百度坐标
搜狐搜狗地图API 搜狗坐标
图吧MapBar地图API 图吧坐标
2、坐标系转换、判断坐标点是否在区域内 工具类
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import java.awt.geom.Path2D;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 地球坐标系、火星坐标系等相互转换、判断点是否在区域内
*
* @Author: pdx
* @Date: 2023/2/24 9:04
* @Version 1.0
*/
/**
* 地球坐标系 (WGS-84) 相互转火星坐标系 (GCJ-02) 的转换算法
* <p>
* 1.各坐标系简介
* WGS84坐标系
* 即地球坐标系,国际上通用的坐标系。
* 设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系。谷歌地图采用的是WGS84地理坐标系(中国范围除外,谷歌中国地图采用的是GCJ02地理坐标系。)
* <p>
* GCJ02坐标系
* 即火星坐标系,WGS84坐标系经加密后的坐标系。
* 出于国家安全考虑,国内所有导航电子地图必须使用国家测绘局制定的加密坐标系统,即将一个真实的经纬度坐标加密成一个不正确的经纬度坐标。
* <p>
* BD09坐标系
* 即百度坐标系,GCJ02坐标系经加密后的坐标系。搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。
* <p>
* 各主流地图API采用的坐标系
* 高德MapABC地图API 火星坐标
* 腾讯搜搜地图API 火星坐标
* 阿里云地图API 火星坐标
* 灵图51ditu地图API 火星坐标
* <p>
* 百度地图API 百度坐标
* 搜狐搜狗地图API 搜狗坐标
* 图吧MapBar地图API 图吧坐标
*/
public class CoordinatesPointUtil {
/**
* 圆周率
*/
private static double pi = 3.14159265358979324D;
/**
* WGS 长轴半径
*/
private static double a = 6378245.0D;
/**
* WGS 偏心率的平方
*/
private static double ee = 0.00669342162296594323D;
private static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
/**
* 84->gcj02
* 地球坐标系 -> 火星坐标系
*
* @param lon 经度
* @param lat 纬度
* @return
*/
public static Map<String, Double> transform(double lon, double lat) {
HashMap<String, Double> localHashMap = new HashMap<String, Double>();
if (outofChina(lat, lon)) {
localHashMap.put("lon", Double.valueOf(lon));
localHashMap.put("lat", Double.valueOf(lat));
return localHashMap;
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 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 mgLat = lat + dLat;
double mgLon = lon + dLon;
localHashMap.put("lon", mgLon);
localHashMap.put("lat", mgLat);
return localHashMap;
}
// gcj02-84
/**
* gcj02 -> 84
* 火星坐标系 -> 地球坐标系
*
* @param lon 经度
* @param lat 纬度
* @return
*/
public static Map<String, Double> gcj2wgs(double lon, double lat) {
Map<String, Double> localHashMap = new HashMap<String, Double>();
double lontitude = lon
- (((Double) transform(lon, lat).get("lon")).doubleValue() - lon);
double latitude = (lat - (((Double) (transform(lon, lat)).get("lat"))
.doubleValue() - lat));
localHashMap.put("lon", lontitude);
localHashMap.put("lat", latitude);
return localHashMap;
}
/**
* 火星坐标转换为百度坐标
*
* @param gg_lon 经度
* @param gg_lat 纬度
*/
public static Map<String, Double> bd_encrypt(double gg_lon, double gg_lat) {
Map<String, Double> bdlocalHashMap = new HashMap<String, Double>();
double x = gg_lon, y = gg_lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
double bd_lon = z * Math.cos(theta) + 0.0065;
double bd_lat = z * Math.sin(theta) + 0.006;
bdlocalHashMap.put("lon", bd_lon);
bdlocalHashMap.put("lat", bd_lat);
return bdlocalHashMap;
}
/**
* 84转百度
* 地球转百度
*
* @param longitude 经度
* @param latitude 纬度
* @return
*/
public static Map<String, Double> wgs84_bd09(double longitude, double latitude) {
//1,将84转国测局gcj-02
Map<String, Double> mapForGCJ = transform(longitude, latitude);
Double lonGCJ = mapForGCJ.get("lon");
Double latGCJ = mapForGCJ.get("lat");
//2.将gcj-02转百度
Map<String, Double> mapForBD09 = bd_encrypt(latGCJ, lonGCJ);
return mapForBD09;
}
/**
* 百度转 火星 gcj02
*/
public static Map<String, Double> bd09togcj02(double bd_lon, double bd_lat) {
Map<String, Double> bdtogcmap = new HashMap<>();
double x = bd_lon - 0.0065;
double y = bd_lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
double gg_lng = z * Math.cos(theta);
double gg_lat = z * Math.sin(theta);
bdtogcmap.put("lon", gg_lng);
bdtogcmap.put("lat", gg_lat);
return bdtogcmap;
}
/**
* 百度转 地球84
*/
public static Map<String, Double> bd09to84(double bd_lon, double bd_lat) {
Map<String, Double> bdtogcmap = bd09togcj02(bd_lon, bd_lat);
Double lon = bdtogcmap.get("lon");
Double lat = bdtogcmap.get("lat");
Map<String, Double> gcto84map = gcj2wgs(lon, lat);
return gcto84map;
}
/**
* 判断点是否在区域内
*
* @param polygon 区域经纬度json字符串
* @param longitude 经度
* @param latitude 纬度
* @return 返回true跟false
*/
public static boolean isPoint(String polygon, double longitude, double latitude) {
JSONArray jsonArray = JSON.parseArray(polygon);
//将json转换成对象
List<ScopeRequest> list = JSON.parseArray(jsonArray.toJSONString(), ScopeRequest.class);
Path2D path2D = create(list);
//true如果指定的坐标在Shape边界内; 否则为false 。
return path2D.contains(longitude, latitude);
}
/**
* 使用Path2D创建一个多边形
*
* @param polygon 经纬度 集合
* @return 返回Path2D.Double
*/
private static Path2D.Double create(List<ScopeRequest> polygon) {
//创建path2D对象
Path2D.Double generalPath = new Path2D.Double();
//获取第一个起点经纬度的坐标
ScopeRequest first = polygon.get(0);
//通过移动到以double精度指定的指定坐标,把第一个起点添加到路径中
generalPath.moveTo(first.getLongitude(), first.getLatitude());
//把集合中的第一个点删除防止重复添加
polygon.remove(0);
//循环集合里剩下的所有经纬度坐标
for (ScopeRequest d : polygon) {
//通过从当前坐标绘制直线到以double精度指定的新指定坐标,将路径添加到路径。
//从第一个点开始,不断往后绘制经纬度点
generalPath.lineTo(d.getLongitude(), d.getLatitude());
}
// 最后要多边形进行封闭,起点及终点
generalPath.lineTo(first.getLongitude(), first.getLatitude());
//将直线绘制回最后一个 moveTo的坐标来关闭当前子路径。
generalPath.closePath();
return generalPath;
}
/**
* 中国坐标内
*
* @param lat 纬度
* @param lon 经度
* @return
*/
public 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;
}
public 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;
}
public 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 class ScopeRequest {
private Double longitude;
private Double latitude;
public ScopeRequest() {
}
public ScopeRequest(Double longitude, Double latitude) {
this.longitude = longitude;
this.latitude = latitude;
}
}
3、使用
public void testPoint() {
Double longitude = 113.73833333333333;
Double latitude = 22.856666666666666;
//判断坐标是否在指定范围内
//区域指标
String area = "[{\"longitude\":113.65052685099445,\"latitude\":22.824908507785644},{\"longitude\":113.64822626450176,\"latitude\":22.825632039022434},{\"longitude\":113.6399128216911,\"latitude\":22.828378879748556},{\"longitude\":113.63436153664783,\"latitude\":22.831287250224182},{\"longitude\":113.62905789669807,\"latitude\":22.836129327366223},{\"longitude\":113.62624769320206,\"latitude\":22.833767617021206},{\"longitude\":113.62267410116758,\"latitude\":22.825636897577045},{\"longitude\":113.61849358338274,\"latitude\":22.820459394024212},{\"longitude\":113.61170820364872,\"latitude\":22.81444546219262},{\"longitude\":113.61023296850541,\"latitude\":22.813297131119313},{\"longitude\":113.60859390988011,\"latitude\":22.811893708506787},{\"longitude\":113.60552826677758,\"latitude\":22.809416442845645},{\"longitude\":113.60607541430429,\"latitude\":22.808786194249834},{\"longitude\":113.60650800900952,\"latitude\":22.808211180848325},{\"longitude\":113.60734124334928,\"latitude\":22.80722299621359},{\"longitude\":113.6103369623189,\"latitude\":22.803566715667042},{\"longitude\":113.64682541465535,\"latitude\":22.75743868593322},{\"longitude\":113.65825492099916,\"latitude\":22.741973885420492},{\"longitude\":113.67124736855725,\"latitude\":22.72594653992477},{\"longitude\":113.68077546696753,\"latitude\":22.717980884824186},{\"longitude\":113.70999444238491,\"latitude\":22.726834382110745},{\"longitude\":113.74515164674901,\"latitude\":22.729278187166013},{\"longitude\":113.74880700731542,\"latitude\":22.73431125977091},{\"longitude\":113.75458539183593,\"latitude\":22.74008256841958},{\"longitude\":113.76528919525289,\"latitude\":22.747602720473147},{\"longitude\":113.76663725001177,\"latitude\":22.750796930182933},{\"longitude\":113.76288734236499,\"latitude\":22.753108710176157},{\"longitude\":113.75782468997326,\"latitude\":22.74867996266583},{\"longitude\":113.74971607616936,\"latitude\":22.757151590356145},{\"longitude\":113.750600834551,\"latitude\":22.759037096438643},{\"longitude\":113.74099704115042,\"latitude\":22.761293726841227},{\"longitude\":113.73325408167987,\"latitude\":22.765064845081536},{\"longitude\":113.72826272961547,\"latitude\":22.76570054906868},{\"longitude\":113.72296538647286,\"latitude\":22.769050441372162},{\"longitude\":113.71939633949256,\"latitude\":22.777781945014027},{\"longitude\":113.72022682667533,\"latitude\":22.775879453838286},{\"longitude\":113.71931147732288,\"latitude\":22.779681081681755},{\"longitude\":113.71437131534617,\"latitude\":22.7867011908682},{\"longitude\":113.70919178027418,\"latitude\":22.78877673250503},{\"longitude\":113.70602977734606,\"latitude\":22.791815078563502},{\"longitude\":113.70333053581464,\"latitude\":22.796790345308064},{\"longitude\":113.69767490739432,\"latitude\":22.80131284144102},{\"longitude\":113.70221068374987,\"latitude\":22.805504603992116},{\"longitude\":113.70020631731316,\"latitude\":22.810803734698652},{\"longitude\":113.7065022894591,\"latitude\":22.810239593076517},{\"longitude\":113.7069975799168,\"latitude\":22.806342887679417},{\"longitude\":113.71030467414265,\"latitude\":22.804881724080417},{\"longitude\":113.71542722281255,\"latitude\":22.805137453931366},{\"longitude\":113.71630227187349,\"latitude\":22.807419030643644},{\"longitude\":113.72116408395344,\"latitude\":22.805420677543058},{\"longitude\":113.72632814010831,\"latitude\":22.806991341644956},{\"longitude\":113.72727458299788,\"latitude\":22.810463838914416},{\"longitude\":113.7244737772436,\"latitude\":22.81388034028834},{\"longitude\":113.72920863045192,\"latitude\":22.814642248968315},{\"longitude\":113.73411011556037,\"latitude\":22.811084814139633},{\"longitude\":113.73601745531245,\"latitude\":22.805872591111154},{\"longitude\":113.74346235660745,\"latitude\":22.807673875160898},{\"longitude\":113.74823545804544,\"latitude\":22.809449427719752},{\"longitude\":113.74892951397094,\"latitude\":22.815132336016408},{\"longitude\":113.75619359061737,\"latitude\":22.824122242787382},{\"longitude\":113.75795391011285,\"latitude\":22.82193420516432},{\"longitude\":113.76357739774382,\"latitude\":22.82163055337918},{\"longitude\":113.76417143565757,\"latitude\":22.82410102899934},{\"longitude\":113.76797854563756,\"latitude\":22.823145212921872},{\"longitude\":113.77126436385585,\"latitude\":22.82568209098946},{\"longitude\":113.77452356590061,\"latitude\":22.832758785166046},{\"longitude\":113.78462710136652,\"latitude\":22.83595616626837},{\"longitude\":113.78443235927783,\"latitude\":22.838100022544666},{\"longitude\":113.7889734728652,\"latitude\":22.838424015560403},{\"longitude\":113.79432050990738,\"latitude\":22.843153430070345},{\"longitude\":113.79708798233801,\"latitude\":22.841214376946425},{\"longitude\":113.79861272420509,\"latitude\":22.8433198572514},{\"longitude\":113.80316636576548,\"latitude\":22.845559693832286},{\"longitude\":113.80668843751758,\"latitude\":22.849121956562612},{\"longitude\":113.80229163247365,\"latitude\":22.858728423098285},{\"longitude\":113.79997674217155,\"latitude\":22.858377966133332},{\"longitude\":113.79178715051151,\"latitude\":22.86128085444187},{\"longitude\":113.7844243413804,\"latitude\":22.865623245056952},{\"longitude\":113.78018269150832,\"latitude\":22.873340907123577},{\"longitude\":113.7732358228895,\"latitude\":22.87530659748961},{\"longitude\":113.77195465643565,\"latitude\":22.88149455602678},{\"longitude\":113.77021731594355,\"latitude\":22.88335211694772},{\"longitude\":113.76933967082468,\"latitude\":22.888039355072976},{\"longitude\":113.76863224172449,\"latitude\":22.88629615718367},{\"longitude\":113.7607629470999,\"latitude\":22.882644205114726},{\"longitude\":113.76011987158208,\"latitude\":22.882382719024008},{\"longitude\":113.75701504616109,\"latitude\":22.88219862477962},{\"longitude\":113.7561130750375,\"latitude\":22.881958604389013},{\"longitude\":113.75368922065934,\"latitude\":22.881706349829415},{\"longitude\":113.75151270892913,\"latitude\":22.88053618976846},{\"longitude\":113.75013375026039,\"latitude\":22.877429003852622},{\"longitude\":113.7483828609701,\"latitude\":22.877070388817174},{\"longitude\":113.74835316962547,\"latitude\":22.877060317707},{\"longitude\":113.74748444375044,\"latitude\":22.876595770107656},{\"longitude\":113.74718684314381,\"latitude\":22.875935086370983},{\"longitude\":113.74659395283433,\"latitude\":22.875390588612447},{\"longitude\":113.7435562206671,\"latitude\":22.873361164863233},{\"longitude\":113.73726288038131,\"latitude\":22.87337002472378},{\"longitude\":113.73054478636325,\"latitude\":22.872310717168144},{\"longitude\":113.72765235615658,\"latitude\":22.873782264984413},{\"longitude\":113.72127603124866,\"latitude\":22.869658961753093},{\"longitude\":113.720753517223,\"latitude\":22.866053248987214},{\"longitude\":113.7175565395653,\"latitude\":22.86519451974749},{\"longitude\":113.71751196019294,\"latitude\":22.86691008829194},{\"longitude\":113.72163262968266,\"latitude\":22.870352246603602},{\"longitude\":113.71963919248458,\"latitude\":22.872499653587564},{\"longitude\":113.72350584035668,\"latitude\":22.87402977595593},{\"longitude\":113.72562760295729,\"latitude\":22.876307375631374},{\"longitude\":113.72514222982332,\"latitude\":22.879568712481728},{\"longitude\":113.72618458919005,\"latitude\":22.881755081656475},{\"longitude\":113.72319930045549,\"latitude\":22.881014022484408},{\"longitude\":113.72250430680228,\"latitude\":22.882003730420305},{\"longitude\":113.72247157532843,\"latitude\":22.882025989820818},{\"longitude\":113.72067163773507,\"latitude\":22.88235111316067},{\"longitude\":113.71698915656086,\"latitude\":22.881341694090903},{\"longitude\":113.7139312819414,\"latitude\":22.880050832295467},{\"longitude\":113.7129685467066,\"latitude\":22.879464018740407},{\"longitude\":113.71189166124292,\"latitude\":22.879033835846997},{\"longitude\":113.71147070720534,\"latitude\":22.879049166613356},{\"longitude\":113.7084584772929,\"latitude\":22.88054059116558},{\"longitude\":113.7069555786569,\"latitude\":22.879841877320022},{\"longitude\":113.7040370354356,\"latitude\":22.878636885007722},{\"longitude\":113.7035370837592,\"latitude\":22.87996078003101},{\"longitude\":113.70089455992375,\"latitude\":22.881480153053417},{\"longitude\":113.69894148955734,\"latitude\":22.881723210971188},{\"longitude\":113.69514856033632,\"latitude\":22.881089807647474},{\"longitude\":113.69032239425738,\"latitude\":22.88100403451165},{\"longitude\":113.68921936200641,\"latitude\":22.880442644743372},{\"longitude\":113.68864242766834,\"latitude\":22.8802094098441},{\"longitude\":113.68030193530545,\"latitude\":22.877561381164014},{\"longitude\":113.67666553694984,\"latitude\":22.87347738229181},{\"longitude\":113.66952334413088,\"latitude\":22.871252574688924},{\"longitude\":113.66650103295731,\"latitude\":22.869191048370737},{\"longitude\":113.6646295746507,\"latitude\":22.870690917897093},{\"longitude\":113.65977442088264,\"latitude\":22.868160189734795},{\"longitude\":113.65302379554976,\"latitude\":22.862724062702853},{\"longitude\":113.65020156053536,\"latitude\":22.861883535544795},{\"longitude\":113.65063013937888,\"latitude\":22.860886732643966},{\"longitude\":113.65063687187568,\"latitude\":22.859881865554826},{\"longitude\":113.64789060847237,\"latitude\":22.858722154937706},{\"longitude\":113.6450396121887,\"latitude\":22.855627431028722},{\"longitude\":113.64594409174539,\"latitude\":22.85403127492708},{\"longitude\":113.64686949816641,\"latitude\":22.852271360786233},{\"longitude\":113.64772936891379,\"latitude\":22.849684264752113},{\"longitude\":113.6478426236727,\"latitude\":22.847606197644783},{\"longitude\":113.64809338050058,\"latitude\":22.84204754568185},{\"longitude\":113.64892440468782,\"latitude\":22.839447861568377},{\"longitude\":113.65002297762257,\"latitude\":22.83709937475891},{\"longitude\":113.65100680212483,\"latitude\":22.8339922280382},{\"longitude\":113.64983257690167,\"latitude\":22.83001438108181},{\"longitude\":113.64864259124752,\"latitude\":22.830822313976626},{\"longitude\":113.64888568262346,\"latitude\":22.82931645042493},{\"longitude\":113.64904612048065,\"latitude\":22.825430893847116},{\"longitude\":113.65052685099445,\"latitude\":22.824908507785644}]";
boolean point = CoordinatesPointUtil.isPoint(area, longitude, latitude);
System.out.println("坐标是否在指定范围内:" + point);
// 坐标系转换
Map<String, Double> stringDoubleMap = CoordinatesPointUtil.gcj2wgs(longitude, latitude);
System.out.println("转换后坐标系:" + stringDoubleMap.toString());
}
参考:
https://zhuanlan.zhihu.com/p/363528840
https://nowjava.com/docs/java-api-11/java.desktop/java/awt/geom/Path2D.html