总结的一些地图坐标计算方法,包括:
地球坐标、百度坐标、火星坐标相互转换
两点坐标距离计算根据坐标及半径求坐标范围(附近的XXX功能)package com.thon.commons.utils;import java.text.DecimalFormat;
/**
* @ClassName: MapUtil * @author: SuperZemo * @email: chenzeming@lanbaoo.com * @Date 10/21/14 14:21 * @Description 地图工具类 * 参考文档: * https://github.com/googollee/eviltransform/blob/master/c/transform.c * http://www.cnblogs.com/kelite/p/3549390.html * http://my.oschina.net/lcdmusic/blog/343505 * http://tech.meituan.com/lucene-distance.html */public class MapUtil { private static final double PI = 3.14159265358979324; //圆周率 private static final double R = 6378245.0; //地球半径 单位:米 private static final double ee = 0.00669342162296594323; private final static DecimalFormat DOUBLE_FORMAT = new DecimalFormat("#.000000"); private final static double DEFAULT_LNG = 116.390471;// 默认经度 private final static double DEFAULT_LAT = 39.861012;// 默认纬度 private double mgLat; private double mgLon;/**
* WGS-84 to GCJ-02 * 地球坐标转换火星坐标 * * @param wgLat wgs84坐标纬度 * @param wgLon wgs84坐标精度 */ public void wgs2gcj(double wgLat, double wgLon) { if (outOfChina(wgLat, wgLon)) { this.mgLat = wgLat; this.mgLon = wgLon; return; } double dLat = transformLat(wgLon - 105.0, wgLat - 35.0); double dLon = transformLon(wgLon - 105.0, wgLat - 35.0); double radLat = toRadians(wgLat); double magic = Math.sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((R * (1 - ee)) / (magic * sqrtMagic) * PI); dLon = (dLon * 180.0) / (R / sqrtMagic * Math.cos(radLat) * PI); this.mgLat = wgLat + dLat; this.mgLon = wgLon + dLon; }/**
* GCJ-02 to WGS-84 * 火星坐标转换地球坐标 * * @param gcjLat * @param gcjLng */ public void gcj2wgs(double gcjLat, double gcjLng) {if (outOfChina(gcjLat, gcjLng)) {
this.mgLat = gcjLat; this.mgLon = gcjLng; return; } double dLat = transformLat(gcjLng - 105.0, gcjLat - 35.0); double dLon = transformLon(gcjLng - 105.0, gcjLat - 35.0); double radLat = toRadians(gcjLat); double magic = Math.sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((R * (1 - ee)) / (magic * sqrtMagic) * PI); dLon = (dLon * 180.0) / (R / sqrtMagic * Math.cos(radLat) * PI); this.mgLat = gcjLat - dLat; this.mgLon = gcjLng - dLon; }/**
* DB-09 To GCJ-02 * 百度坐标转换火星坐标 * * @param bdLat 百度坐标纬度 * @param bdLon 百度坐标精度 */ public void db2gcj(double bdLat, double bdLon) { if (outOfChina(bdLat, bdLon)) { this.mgLat = bdLat; this.mgLon = bdLon; return; } double x = bdLon - 0.0065, y = bdLat - 0.006; double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * PI * 3000.0 / 180.0); double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * PI * 3000.0 / 180.0); this.mgLon = z * Math.cos(theta); this.mgLat = z * Math.sin(theta); }/**
* GCJ-02 To DB-09 * 火星坐标转换百度坐标 * * @param bdLat 百度坐标纬度 * @param bdLon 百度坐标精度 */ public void gcj2db(double bdLat, double bdLon) { if (outOfChina(bdLat, bdLon)) { this.mgLat = bdLat; this.mgLon = bdLon; return; } double x = bdLon, y = bdLat; double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * PI * 3000.0 / 180.0); double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * PI * 3000.0 / 180.0); this.mgLon = z * Math.cos(theta) + 0.0065; this.mgLat = z * Math.sin(theta) + 0.006; } 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; }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; }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; }/**
* 获取坐标距离(米) * * @param lng1 起始经度 * @param lat1 起始纬度 * @param lng2 目地地经度 * @param lat2 目的地纬度 * @return */ public static int getDistance(double lng1, double lat1, double lng2, double lat2) { /*double x, y, distance; x = (lon2 - lon1) * PI * R * Math.cos(((lat1 + lat2) / 2) * PI / 180) / 180; y = (lat2 - lat1) * PI * R / 180; distance = Math.hypot(x, y); return (int) (distance + 0.5);*/ double dx = lng1 - lng2; // 经度差值 double dy = lat1 - lat2; // 纬度差值 double b = (lat1 + lat2) / 2.0; // 平均纬度 double Lx = toRadians(dx) * R * Math.cos(toRadians(b)); // 东西距离 double Ly = R * toRadians(dy); // 南北距离 return (int) Math.sqrt(Lx * Lx + Ly * Ly); }public static double toRadians(double x) {
return x * PI / 180; }/**
* 将String经度转换成Double * * @param lon * @return */ public static double getLongitude(String lon) { if (StringUtils.isBlank(lon)) { return DEFAULT_LNG; } if (lon.length() > 10) { lon = lon.substring(0, 10); } return StringUtils.toDouble(lon); }/**
* 将String纬度转换成Double * * @param lat * @return */ public static double getLatitude(String lat) { if (StringUtils.isBlank(lat)) { return DEFAULT_LAT; } if (lat.length() > 10) { lat = lat.substring(0, 10); } return StringUtils.toDouble(lat); }/**
* 根据距离返回,经纬度范围 返回顺序 minLat,minLng,maxLat,maxLng * * @param lat * @param lon * @param raidus 距离(半径)单位:米 * @return */ public static double[] getAround(double lat, double lon, int raidus) {try {
Double latitude = lat; Double longitude = lon;Double degree = (24901 * 1609) / 360.0; // 赤道周长24901英里 1609是转换成米的系数
Double dpmLat = 1 / degree;
Double radiusLat = dpmLat * raidus; Double minLat = latitude - radiusLat; Double maxLat = latitude + radiusLat;Double mpdLng = degree * Math.cos(toRadians(latitude));
Double dpmLng = 1 / mpdLng; Double radiusLng = dpmLng * raidus; Double minLng = longitude - radiusLng; Double maxLng = longitude + radiusLng;// 格式化
minLat = Double.parseDouble(DOUBLE_FORMAT.format(minLat)); minLng = Double.parseDouble(DOUBLE_FORMAT.format(minLng)); maxLat = Double.parseDouble(DOUBLE_FORMAT.format(maxLat)); maxLng = Double.parseDouble(DOUBLE_FORMAT.format(maxLng));return new double[]{minLat, minLng, maxLat, maxLng};
} catch (NumberFormatException e) { } return null; }/**
* 判断是否超出规定距离范围 * * @param lon1 起始经度 * @param lat1 起始纬度 * @param lon2 目地地经度 * @param lat2 目的地纬度 * @param lat2 目的地纬度 * @return */ public static boolean isOutOfRange(double lon1, double lat1, double lon2, double lat2, double raidus) { int distance = getDistance(lon1, lat1, lon2, lat2); if (distance > raidus) { return Boolean.TRUE; } return Boolean.FALSE; }void delta(double lat, double lng) {
}
public double getMgLat() {
return mgLat; }public double getMgLon() {
return mgLon; }public static void main(String[] args) {
double lat1 = 30.67521931451247; double lat2 = 30.681872; double lng1 = 104.0970145349406; double lng2 = 104.104885;System.out.println(getDistance(lng1, lat1, lng2, lat2));
}} 原文转自:https://www.oschina.net/question/1249849_249749