地图坐标相关计算

总结的一些地图坐标计算方法,包括:

地球坐标、百度坐标、火星坐标相互转换
两点坐标距离计算
根据坐标及半径求坐标范围(附近的XXX功能)
package com.thon.commons.utils;

import java.text.DecimalFormat;

/**
* @ClassName: MapUtil
* @author: SuperZemo
* @email: [email protected]
* @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

原文地址:https://www.cnblogs.com/Seamless/p/10271780.html

时间: 2024-10-14 00:34:58

地图坐标相关计算的相关文章

根据地图上的两个点各自的x,y坐标,计算出2点之间的直线距离。显示为公里、米

/** * calc_map_distance() , 根据地图上的两个点各自的x,y坐标,计算出2点之间的直线距离 * @param array $point_1 第1个点的x,y坐标 array( 101 , 202 ) * @param array $point_2 第2个点的x,y坐标 array( 101 , 202 ) * @param bool $calc_as_string 是否计算为字符串公里距离 , 如果未否返回数字 * @return float | false | str

微信开发之附近商家地理位置计算和腾讯地图坐标转百度地图坐标的方法

原文:微信开发之附近商家地理位置计算和腾讯地图坐标转百度地图坐标的方法 腾讯地图坐标转百度坐标 案例:本次开发的系统是一个商家联盟积分系统.在全国各地都有商家联盟的网点. 要求实现的功能 a.微信粉丝通过微信号就能查看附近的商家 b.我的联盟系统统计在2公里之内的商家网点 c.并标出商家和粉丝位置的距离是多少米. d.在商家的详细介绍页面设置百度地图接入步行.公交.驾车一键导航功能 那么现在问题来了: 问题1:在做微信O2O开发的过程中,通过微信地理位置功能事件获得的是腾讯地图坐标.而我们的导航

从百度地图API中抠出来的一个js方法,计算百度地图坐标距离

从百度地图api(http://developer.baidu.com/map/jsdemo.htm#a6_1)中抠出来的一个js方法,计算百度地图坐标距离 可读行还没还原,能用就行~ function fD(a, b, c) { for (; a > c;) a -= c - b; for (; a < b;) a += c - b; return a; }; function jD(a, b, c) { b != null && (a = Math.max(a, b));

微信JS-SDK坐标位置转换为百度地图坐标

微信JS-SDK开发过程中,使用getLocation获取坐标位置,如何将微信获取的坐标直接应用到百度地图中,显示以下效果: 说明:红色图标是从微信转换过来的位置,蓝色图标是周边位置.首先从微信开发流程讲解. 1.微信JS-SDK开发文档 首先进入官网的帮助文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN 可对文档进行详细的研读,要获取位置信息,分以下步骤:

谷歌地图瓦片相关操作(js,google Maps v3)

前段时间,由于工作原因,研究了谷歌地图的瓦片相关操作.已知一个点的经纬度和地图级别,获取该点所在的瓦片的url:已知一个瓦片的url,计算该瓦片左上角经纬度:已知一个点经纬度和地图级别,计算这个点在世界地图上的像素值. 1.已知一个点的经纬度和地图级别,获取该点所在的瓦片的url 参考了两篇博客:这个博客(http://blog.csdn.net/lijun_xiao2009/article/details/8178578)中的原理,但是使用到的公式太难算了,就结合了另一篇博客(http://b

随鼠标移动在状态栏实时显示地图坐标(转载)

任务描述    鼠标在地图上移动时,会产生一系列mousemove(鼠标移动)事件,我们可以在客户端通过javascript脚本捕捉到鼠标事件的坐标,这个坐标是基于浏览器窗口的屏幕坐标.如果要显示鼠标点所在的地图坐标,有两种方法:第一,不停地向服务器发送AJAX请求,在服务器端将屏幕坐标转换成地图坐标,然后返回客户端,显示在状态栏.这样的话会有一个问题,就是鼠标拖动的时候会一直不停地发送请求,极大地增加了服务器的负担.当然,我们可以通过设置时间间隔,比如半秒钟更新一次坐标,达到视觉效果与服务器负

根据城市名获取百度地图坐标API

最近项目中百度地图的相关操作当没有坐标的时候默认通过城市名称获取中心点,不过感觉有点慢到网上搜索了一下也没类似的城市对应的价格的数据库.所以自己就建了一个.现公开出来供大家使用接口调用方法 http://2.ibtf.sinaapp.com/map/?city=北京返回json串 {"x":"116.403874","y":"39.914889"} 注1.城市名请用UTF-8编码否则会出错2.如返回 please reload

总结与元素坐标相关的属性(再也搞不混了)

与元素坐标相关属性: 1.HTML元素 html元素是网页的根元素,document.documentElement就指向这个元素. 1.1 clientWidth, clientHeight 这两个属性返回视口(viewport)的大小,单位为像素.所谓“视口”,是指用户当前能够看见的那部分网页的大小.document.documentElement.clientWidth和document.documentElement.clientHeight,基本上与window.innerWidth和

iOS 火星坐标相关整理及解决方案汇总(转)

这几天在处理定位相关的代码,彻彻底底的被火星坐标恶心到了. 恶心列表 从 CLLocationManager 取出来的经纬度放到 mapView 上显示,是错的! 从 CLLocationManager 取出来的经纬度去 Google Maps API 做逆地址解析,当然是错的! 从 MKMapView 取出来的经纬度去 Google Maps API 做逆地址解析终于对了.去百度地图API做逆地址解析,依旧是错的! 从上面两处取的经纬度放到百度地图上显示都是错的!错的!的! 当时我还不知道火星