`

根据地图坐标经纬度返回相应的地理位置

阅读更多

 

 一.在进行根据地图坐标经纬度返回相应的地理位置之前我们应该了解下地图坐标系:

1、大地坐标系统 WGS-84

用来表述地球上点的位置的一种地区坐标系统。它采用一个十分近似于地球自然形状的参考椭球作为描述和推算地面点位置和相互关系的基准面。一个大地坐标系统必须明确定义其三个坐标轴的方向和其中心的位置。通常人们用旋转椭球的短轴与某一规定的起始子午面分别平行干地球某时刻的平均自转轴和相应的真起始子午面来确定坐标轴的方向。若使参考椭球中心与地球平均质心重合,则定义和建立了地心大地坐标系。它是航天与远程武器和空间科学中各种定位测控测轨的依据。若椭球表面与一个或几个国家的局部大地水准面吻合最好,则建立了一个国家或区域的局部大地坐标系。大地坐标系中点的位置是以其大地坐标表示的,大地坐标均以椭球面的法线来定义。其中,过某点的椭球面法线与椭球赤道面的交角为大地纬度;包含该法线和大地子午面与起始大地子午面的二面角为该点的大地经度;沿法线至椭球面的距离为该点的大地高。大地纬度、大地经度和大地高分别用大写英文字母B、L、H表示。

国内的互联网公司,都不会使用GPS坐标,因为这不符合国家政策。所以大家都会使用GCJ-02坐标系。

 

2、火星坐标系统 GCJ-02

国家保密插件,也叫做加密插件或者加偏或者SM模组,其实就是对真实坐标系统进行人为的加偏处理,按照几行代码的算法,将真实的坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。而加密后的坐标也常被人称为火星坐标系统。

目前使用火星坐标系的地图商:

  • 腾讯搜搜地图
  • 搜狐搜狗地图
  • 阿里云地图
  • 高德MapABC地图
  • 灵图51ditu地图

所有的电子地图所有的导航设备,都需要加入国家保密插件。第一步,地图公司测绘地图,测绘完成后,送 到国家测绘局,将真实坐标的电子地图,加密成“火星坐标”,这样的地图才是可以出版和发布的,然后才可以让GPS公司处理。第二步,所有的GPS公司,只要需要汽车导航的,需要用到导航电子地图的,统统需要在软件中加入国家保密算法,将COM口读出来的真实的坐标信号,加密转换成国家要求的保密的坐标,这样,GPS导航仪和导航电子地图就可以完全匹配,GPS也就可以正常工作。

国内互联网公司,都必须使用GCJ-02坐标系。

 

 

3、百度坐标系统 BD-09

百度坐标对火星坐标系进行了一次加密,形成了百度坐标系.

目前使用百度坐标系的地图商:

  • 百度Baidu地图

少部分公司会在GCJ-02的基础上再进行一次加密,但这样的坐标不通用,只适于特定公司的地图。

 

4、图吧

图吧是百度坐标乘以10000的结果。

目前使用图吧坐标系的地图商:

  • 图吧MapBar地图

少部分公司会在GCJ-02的基础上再进行一次加密,但这样的坐标不通用,只适于特定公司的地图。

二.地图坐标转换工具类,根据项目中的实际情况将坐标进行相应转换,因为各个地图使用的坐标系不同,必须要使用对应的坐标系经纬度才能返回正确的地理位置.

坐标系转换工具类:

PositionUtil.java
package com.ydtx.utils.gps;

import java.util.HashMap;
import java.util.Map;

import com.ydtx.moudle.controller.carMonitor.PointDouble;
import com.ydtx.utils.BaiduMapUtil;

/** 
 * 各地图API坐标系统比较与转换; 
 * WGS84坐标系:即地球坐标系,国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系, 
 * 谷歌地图采用的是WGS84地理坐标系(中国范围除外); 
 * GCJ02坐标系:即火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。 
 * 谷歌中国地图和搜搜中国地图采用的是GCJ02地理坐标系; BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系; 
 * 搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。 chenhua 
 */  
public class PositionUtil {  
      
    public static final String BAIDU_LBS_TYPE = "bd09ll";  
      
    public static double pi = 3.1415926535897932384626;  
    public static double a = 6378245.0;  
    public static double ee = 0.00669342162296594323;  
  
    /** 
     * 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System 
     *  
     * @param lat 
     * @param lon 
     * @return 
     */  
    public static Gps gps84_To_Gcj02(double lat, double lon) {  
        if (outOfChina(lat, lon)) {  
            return null;  
        }  
        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;  
        return new Gps(mgLat, mgLon);  
    }  
  
    /** 
     * * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return 
     * */  
    public static Gps gcj_To_Gps84(double lat, double lon) {  
        Gps gps = transform(lat, lon);  
        double lontitude = lon * 2 - gps.getWgLon();  
        double latitude = lat * 2 - gps.getWgLat();  
        return new Gps(latitude, lontitude);  
    }  
  
    /** 
     * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标 
     *  
     * @param gg_lat 
     * @param gg_lon 
     */  
    public static Gps gcj02_To_Bd09(double gg_lat, double gg_lon) {  
        double x = gg_lon, y = gg_lat;  
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * pi);  
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * pi);  
        double bd_lon = z * Math.cos(theta) + 0.0065;  
        double bd_lat = z * Math.sin(theta) + 0.006;  
        return new Gps(bd_lat, bd_lon);  
    }  
  
    /** 
     * * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param 
     * bd_lat * @param bd_lon * @return 
     */  
    public static Gps bd09_To_Gcj02(double bd_lat, double bd_lon) {  
        double x = bd_lon - 0.0065, y = bd_lat - 0.006;  
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * pi);  
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * pi);  
        double gg_lon = z * Math.cos(theta);  
        double gg_lat = z * Math.sin(theta);  
        return new Gps(gg_lat, gg_lon);  
    }  
  
    /** 
     * (BD-09)-->84 
     * @param bd_lat 
     * @param bd_lon 
     * @return 
     */  
    public static Gps bd09_To_Gps84(double bd_lat, double bd_lon) {  
  
        Gps gcj02 = PositionUtil.bd09_To_Gcj02(bd_lat, bd_lon);  
        Gps map84 = PositionUtil.gcj_To_Gps84(gcj02.getWgLat(),  
                gcj02.getWgLon());  
        return map84;  
  
    }  
  
    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 Gps transform(double lat, double lon) {  
        if (outOfChina(lat, lon)) {  
            return new Gps(lat, lon);  
        }  
        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;  
        return new Gps(mgLat, mgLon);  
    }  
  
    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 static Map GPSToBaiduMap(String log, String lat){
      Map map = new HashMap();
      if(log!=null&&log!=""&&lat!=null&&lat!=""){
         Gps gps=PositionUtil.gps84_To_Gcj02(Double.parseDouble(lat), Double.parseDouble(log));
         lat=String.valueOf(gps.getWgLat());
         log=String.valueOf(gps.getWgLon());
      }
      map.put("lng", log);
      map.put("lat", lat);
      return map;
   }
    public static void main(String[] args) {

        // 北斗芯片获取的经纬度为WGS84地理坐标 31.426896,119.496145
        Gps gps = new Gps(31.426896, 119.496145);
        System.out.println("gps :" + gps);
        Gps gcj = gps84_To_Gcj02(gps.getWgLat(), gps.getWgLon());
        System.out.println("gcj :" + gcj);
        Gps star = gcj_To_Gps84(gcj.getWgLat(), gcj.getWgLon());
        System.out.println("star:" + star);
        Gps bd = gcj02_To_Bd09(gcj.getWgLat(), gcj.getWgLon());
        System.out.println("bd  :" + bd);
        Gps gcj2 = bd09_To_Gcj02(bd.getWgLat(), bd.getWgLon());
        System.out.println("gcj :" + gcj2);
    }
}  

根据gprs坐标经纬度返回对应的地址:

我们项目中采用的是阿里云地图进行地址返回,使用的源数据是大地坐标系统 WGS-84需要转换成火星坐标系GCJ-02,转换之后就可以通过阿里云地图接口进行地址返回

 MapAddressForGprsUtil.java

package com.ydtx.utils;

import java.net.URL;
import java.util.Map;

import com.alibaba.fastjson.JSONArray;
import com.ydtx.utils.gps.PositionUtil;

import net.sf.json.JSONObject;

public class MapAddressForGprsUtil {
   public static void main(String[] args) {  
        String add = getAdd("22.5810633333333","113.848505");  
        System.out.println(add);
    }  
    /**
     * @author lizhiyuan
     * 定义通过经纬度返回地理位置信息
     * @param lat
* @param log
* @return
*/
public static String getAdd( String lat,String log){  
        //lat 小  log  大  
        //参数解释: 经度,纬度, type 001 (100代表道路,010代表POI,001代表门址,111可以同时显示前三项)  
String urlString =null;  
        String res = "";     
        try {   
           //平台和终端用的百度地图需要将经纬度转换成百度地图的经纬度
Map map=PositionUtil.GPSToBaiduMap(log, lat);
           if(map!=null){
              urlString = "http://gc.ditu.aliyun.com/regeocoding?l="+map.get("lat")+","+map.get("lng")+"&type=111";
              map=null;
                URL url = new URL(urlString);    
                java.net.HttpURLConnection conn = (java.net.HttpURLConnection)url.openConnection();    
                conn.setDoOutput(true);    
                conn.setRequestMethod("POST");    
                java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream(),"UTF-8"));    
                String line;    
               while ((line = in.readLine()) != null) {    
                   res += line+"\n";    
             }    
                in.close();    
           }
        } catch (Exception e) {    
            //System.out.println("error in wapaction,and e is " + e.getMessage());    
}   
        JSONObject jsonObject = JSONObject.fromObject(res);  
        JSONArray jsonArray = JSONArray.parseArray(jsonObject.getString("addrList"));  
        JSONObject j_2 = JSONObject.fromObject(jsonArray.get(0));  
        String area = j_2.getString("admName"); 
        String address=null;
        if(area!=null&&!area.equals("")){
           String arrs[] = area.split(",");    
            String arr= j_2.getString("name");
            
            if(arrs.length==3){
               address=arrs[0]+arrs[1]+arrs[2]+arr;
            }else{
               address=arrs[0]+arrs[1]+arr;
            }
            
            JSONObject j_3 = JSONObject.fromObject(jsonArray.get(1));  
            String name = j_3.getString("name"); 
            if(name!=null&&!name.equals("")){
                String addr= j_3.getString("addr");
                address+=name+addr;
            }
        }else{
           JSONObject j_3 = JSONObject.fromObject(jsonArray.get(1));  
            String name = j_3.getString("admName"); 
            if(name!=null&&!name.equals("")){
                String arrs[] = name.split(",");    
                String name1= j_3.getString("name");
                String arr= j_3.getString("addr");
                address=arrs[0]+arrs[1]+arrs[2]+arr+name1;
            }
        }
        
        return address;    
    }  
}

 测试结果为:

log4j:WARN No such property [maxFileSize] in org.apache.log4j.DailyRollingFileAppender.

广东省深圳市宝安区宝源路西乡体育中心银田路18

 

最后总结吧:

1.一定要了解自己源数据是什么坐标

2.因为百度地图需要申请ak而且返回接口次数有限制,参考了网上的一些博客,采用的阿里云地图接口

   但是在项目中发现部分地区:比如新疆 东北 等等一些偏远地区可能阿里云地图没有采集数据所以无法返回

   地理位置信息

分享到:
评论

相关推荐

    天地图搜索及获取经纬度工具 (含大量注释对于初学很有帮助)

    "天地图搜索及获取经纬度工具"是一款专为初学者设计的应用程序,它结合了天地图服务,使得用户能够方便地进行地理位置搜索,并且能够获取到相应的经纬度坐标。这个工具对于那些正在学习地理信息系统(GIS)、Web开发...

    平面坐标与经纬度的转换

    2. 函数调用:根据所需转换类型(平面到经纬度或反之)调用相应的函数,传入对应的参数,如平面坐标值、椭球体类型和投影方式。 3. 数据处理:函数内部会进行复杂的数学计算,如反向/正向解算,以完成坐标转换。 4. ...

    批量经纬度坐标转换工具

    而“转换成对应省份城市”则表明该工具能够根据输入的经纬度,查询并返回这些坐标在哪个省份或城市,这涉及到地理编码(Geocoding)技术,即通过坐标来获取位置的地址信息。 标签“地图应用相关”暗示了这个工具的...

    根据经纬度位置将其按照行政区域分类代码

    本项目涉及的关键技术是根据经纬度坐标将位置数据归类到相应的行政区域代码中。下面,我们将深入探讨这一过程及其相关知识点。 首先,我们要理解经纬度系统。经纬度是一种地理坐标系统,用于确定地球上任何一点的...

    根据IP或经纬度查询城市-离线版.zip

    本资源“根据IP或经纬度查询城市-离线版.zip”提供了一种无需联网即可实现地理位置查询的方法,这对于那些对实时性要求不高但又需要定位功能的场景非常实用。下面将详细探讨这一离线定位技术及其核心组件。 首先,...

    地理坐标和屏幕坐标转换

    在给定的代码中,我们可以看到三个方法,分别用于将地理坐标转换为屏幕坐标,地图坐标(一种特殊类型的地理坐标)转换为页面布局坐标,以及页面布局坐标转换回地图坐标。这些方法在ArcGIS ADF(ArcGIS Desktop ...

    百度地图——导航(地理编码输入地址获取经纬度)

    7. **权限申请**:别忘了在AndroidManifest.xml中添加必要的权限,如INTERNET权限,用于网络请求,以及ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限,用于获取设备的地理位置。 通过以上步骤,开发者可以实现...

    百度地图经纬度定位

    4. 处理返回结果:百度地图API会返回包含定位信息的对象,包括精确的地理位置、精度、速度等。你可以根据这些信息更新地图上的标记或者进行其他处理。 在实际项目中,百度地图经纬度定位可以应用于以下几个方面: ...

    MAPGIS大地坐标和经纬度之间的换算程序

    4. **程序实现**:"MAPGIS大地坐标和经纬度之间的换算程序"即实现了这个过程,用户只需输入相应的大地坐标,程序会自动计算并返回对应的经纬度坐标。反之,也可以将经纬度转换为大地坐标。 5. **应用范围**:这种...

    GOOGLE地图经纬度批量查询

    3. 经纬度返回:API会返回每个地点对应的经纬度坐标,软件将这些信息整理并展示给用户。用户可以导出这些坐标信息,以便进一步使用。 4. 效率优化:批量查询避免了逐个手动搜索的繁琐,尤其适用于处理大量地点的...

    【百度地图】坐标标注控件

    通过获取用户的IP地址,API能够返回对应的地理位置信息,包括但不限于城市级别。这通常是通过调用“IP定位”接口实现的,可以快速为用户提供本地化的地图体验。 2. **用户点击地图标注地图**:此功能允许用户在地图...

    mysql函数-根据经纬度坐标计算距离

    在MySQL数据库中,计算两个地理位置之间的距离通常涉及到地理坐标系统,即经纬度。经纬度坐标是地球表面位置的标准表示方式,其中经度表示东西方向,纬度表示南北方向。本篇文章将详细介绍如何利用MySQL的内置函数和...

    怎么根据百度地图位置获取经纬度?.docx

    在IT行业中,尤其是在地理信息系统(GIS)或者定位服务相关的开发工作中,经常需要根据特定的地理位置信息,如街道地址,获取其对应的经纬度坐标。经纬度是地球表面位置的一种坐标表示方式,经度从0到180度东经和180...

    基于高德地图逆地理编码 获取乡镇/街道边界+百度地图手工描绘边界

    在高德地图API中,可以调用相应的接口,输入经纬度坐标,系统将返回对应的地理位置描述。 2. **高德地图API**: 高德地图提供了一系列开发者服务,包括地图展示、定位、路径规划和地理编码等。注册并认证为高德...

    leaflet 获取经纬度.rar

    这个“leaflet 获取经纬度.rar”压缩包显然是为了帮助开发者实现一个功能,即在Leaflet地图上点击时获取到相应的经纬度坐标。 在Leaflet中,获取地图上的经纬度主要依赖于地图的“click”事件监听器。当用户在地图...

    地区经纬度信息获取(利用Google地图API获取)

    综合上述内容,我们可以了解到,通过Google地图API获取地区经纬度信息是一个涉及网络编程、数据解析和地理知识的复杂过程。开发者在实际应用中需要按照Google地图API的文档进行编程,并根据业务需求灵活地处理和使用...

    Android实现注册登录后 点击获取当前地理位置及经纬度坐标

    在Android应用开发中,获取用户当前的地理位置及经纬度坐标是一项常见的需求,这通常涉及到位置服务、网络通信以及数据解析等多个技术点。本项目通过Android Studio实现了一个完整的流程,包括用户注册登录、与...

    GPS经纬度转百度经纬度

    - 坐标转换需要精确计算,误差可能会随着地理位置的不同而变化。 - 转换过程中可能涉及到浮点数运算,需要考虑精度问题,避免因浮点数误差导致的位置偏差。 - 除了百度地图,其他地图服务提供商如高德、谷歌也有...

    通过地名搜索在谷歌地图上显示地理全名和经纬度

    4. 显示地图:根据获取的经纬度,程序会在地图组件上设置中心点,显示相应位置。 5. 标记位置:在地图上添加一个标记,表示地名对应的地理位置。 6. 经纬度显示:将解析出的经纬度信息展示给用户,通常在地图下方或...

    安卓高德地图开发自定义线路规划(按着自己定义的经纬度规划线路)

    本教程将深入探讨如何使用高德地图API来实现自定义线路规划,即根据用户提供的经纬度数据定制路线。这个过程涉及到地图API的调用、地理坐标处理以及路径算法等多个知识点。 首先,我们需要在项目中集成高德地图SDK...

Global site tag (gtag.js) - Google Analytics