上一篇我们讲到了如何选择地图服务商,这一篇接着上一篇讲下一个比较重要,且大多数开发者会碰到的问题,那就是地图纠偏
先来了解下为什么会存在地图偏移这么一个问题:先参考一个文档
http://baike.baidu.com/view/3163334.htm (百度百科对于火星坐标系统的解释)
http://www.kaixin001.com/repaste/16531379_3916220968.html?uid=16575561&urpid=3916329607
截取部分文字来看:
国家保密插件,也叫做加密插件或者加偏或者SM模组,其实就是对真实坐标系统进行人为的加偏处理,按照几行代码的算法,将真实的坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。而加密后的坐标也常被人称为火星坐标系统
从这个解释看以看出,为了保证国家的领土安全,国家在地图这一层上做了一个认为加偏处理,借助网上一个经典例子来描述:比如某广场的经纬度本身是固定的,但是国家为了保证安全,对其经纬度进行了一个加偏,比如原先是假设(20.0022211,110.2223455),经过处理之后得到的是(20.0022222,110.2223555),变化比较小,但其实已经可能已经不在某广场附近了,这样就达到了安全性,那么国内的地图服务商,GPS导航仪等则在出厂前会对检测到的经纬度同样有一个加偏,这样两个加偏,就凑到一块去了,一张完整的可以使用的地图就出来了。
相信这个例子应该能看出来为什么会存在这个地图偏移了吧,如果还有不懂可以QQ联系:565336905.
那从上面的描述中可以看出,基本国内的地图服务商其实是具有这一个加偏算法的,也就是说如果选择国内的地图服务商,其实表象是不存在地图偏移这么一个问题的,但是如果选择Google地图,我们知道Google 曾在10年申请牌照,但是没有得到批准,也就是说它是不具备地图服务提供资质的。但是依然可以使用啊,但是Google好像是10年那会关闭了纠偏接口,这样凡是国内使用Google地图的开发者来说基本都会发现取到的经纬度跟地图显示偏差很大,这就是地图偏移。
那么如何解决Google地图的偏移问题呢。
我当时做项目的过程中也是遇到这个问题,并且烦了好一阵子,但是后续通过查资料等最后获取到几个方式:
1.纠偏数据库,网上有人售卖这个地图数据库,精度有0.01及0.001的,我后续买了0.001精度的,最后的效果不错,基本看不到偏差了,杭州跟深圳两地有测试过。
2.纠偏插件,也就是一个jar包,通过这个大概1.7M的jar包,据说可以提供大致相关于0.01精度纠偏数据库的精度。不过对于移动开发者而言,或多或少会仔细考虑这1.7M 库的代价。我最后也没有购买,所以不好评价这个效果。
3.网络上有一些纠偏接口提供商,我也测试过,效果也很好,但是由于受限于自己不能控制(服务器是国外的,可能纠偏过程会很慢,又或者别人什么时候把这个服务关闭掉了,所以不敢用)。当然我会提供给大家,供测试或者不太重视这块的开发者使用吧。
最后如需购买Google地图纠偏数据库或者探讨LBS相关问题,可以联系本人:QQ:565336905,加时请注明。
以下是一个免费的地图纠偏接口,本人测试过,还不错,速度包括精度都很好,建议个人开发者学习或者测试的,可以直接使用
package *.*;//自己填写
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import android.os.Bundle;
public class HttpUtil {
/**
* 发送请求
* @param url
* @param method
* @param params
* @param enc
* @return
*/
public static String openUrl(String url, String method, Bundle params, String enc){
String response = null;
//GET请求
if(method.equals("GET")){
if(params != null)
url = url + "?" + encodeUrl(params);
}
try {
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestProperty("User-Agent", System.getProperties().getProperty("http.agent"));
conn.setReadTimeout(10000); //设置超时时间
if(method.equals("POST")){
conn.setRequestMethod("POST");
conn.setDoOutput(true);
if(params != null)
conn.getOutputStream().write(encodeUrl(params).getBytes("UTF-8"));
}
response = read(conn.getInputStream(),enc);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(),e);
}
return response;
}
/**
* 读取输入流,转换为String
* @param in
* @param enc
* @return
* @throws IOException
*/
private static String read(InputStream in, String enc) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader r = null;
if(enc != null){
//按指定的编码读入流
r = new BufferedReader(new InputStreamReader(in,enc), 1000);
}else{
//按默认的编码读入
r = new BufferedReader(new InputStreamReader(in), 1000);
}
for (String line = r.readLine(); line != null; line = r.readLine()) {
sb.append(line);
}
in.close();
return sb.toString();
}
/**
* 按key-Value的方式组拼请求参数
* 参数内通过“=”连接,参数间通过“&”来连接
* @param parameters
* @return
*/
public static String encodeUrl(Bundle parameters) {
if (parameters == null)
return "";
StringBuilder sb = new StringBuilder();
//因为第一个参数和URL之间是通过"?"来连接的
boolean first = true;
for (String key : parameters.keySet()) {
if (first)
first = false;
else
sb.append("&");
sb.append(key + "=" + parameters.getString(key));
}
return sb.toString();
}
/**
* 把数据post到服务器,获取返回的结果
*
* @param uriAPI
* : API 所在的路径
* @param params
* : 传递的数据
*/
public static String postToServer(String uriAPI, List<NameValuePair> params) {
/* 建立HTTPost对象 */
HttpPost httpRequest = new HttpPost(uriAPI);
try {
/* 添加请求参数到请求对象 */
httpRequest.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
/* 发送请求并等待响应 */
HttpResponse httpResponse = new DefaultHttpClient()
.execute(httpRequest);
/* 若状态码为200 ok */
if (httpResponse.getStatusLine().getStatusCode() == 200) {
/* 读返回数据 */
return EntityUtils.toString(httpResponse.getEntity());
} else {
return "Error Response: "
+ httpResponse.getStatusLine().toString();
}
} catch (Exception e) {
return "post failure :caused by-->" + e.getMessage().toString();
}
}
}
package *.*;//自己填写
import android.os.Bundle;
import com.google.android.maps.GeoPoint;
/**
* 主要解决GPS偏移的问题
* @author Administrator
*
*/
public class GPSUtil {
private static String QUERY_URL = "http://www.mapdigit.com/guidebeemap/offsetinchina.php";
private static String METHOD_GET = "GET";
/**
* 获取偏移值
* @param longitude
* @param latitude
* @param path
* @return
*/
public static GeoPoint adjustLoction(double longitude, double latitude) {
Bundle params = new Bundle();
params.putString("lng", String.valueOf(longitude));
params.putString("lat", String.valueOf(latitude));
String offsetString = HttpUtil.openUrl(QUERY_URL, METHOD_GET, params,
CustomParameter.ENCODE);
int index = offsetString.indexOf(",");
if (index > 0) {
// 将坐标值转为18级相应的像素值
double lngPixel = lonToPixel(longitude, 18);
double latPixel = latToPixel(latitude, 18);
// 获取偏移值
String OffsetX = offsetString.substring(0, index).trim();
String OffsetY = offsetString.substring(index + 1).trim();
//加上偏移值
double adjustLngPixel = lngPixel + Double.valueOf(OffsetX);
double adjustLatPixel = latPixel + Double.valueOf(OffsetY);
//由像素值再转为经纬度
double adjustLng = pixelToLon(adjustLngPixel, 18);
double adjustLat = pixelToLat(adjustLatPixel, 18);
return new GeoPoint((int) (adjustLng * 1000000),
(int) (adjustLat * 1000000));
}
//经验公式
return new GeoPoint((int) ((latitude - 0.0025) * 1000000),
(int) ((longitude + 0.0045) * 1000000));
}
/**
* 经度到像素X值
*
* @param lng
* @param zoom
* @return
*/
public static double lonToPixel(double lng, int zoom) {
return (lng + 180) * (256L << zoom) / 360;
}
/**
* 像素X到经度
*
* @param pixelX
* @param zoom
* @return
*/
public static double pixelToLon(double pixelX, int zoom) {
return pixelX * 360 / (256L << zoom) - 180;
}
/**
* 纬度到像素Y
*
* @param lat
* @param zoom
* @return
*/
public static double latToPixel(double lat, int zoom) {
double siny = Math.sin(lat * Math.PI / 180);
double y = Math.log((1 + siny) / (1 - siny));
return (128 << zoom) * (1 - y / (2 * Math.PI));
}
/**
* 像素Y到纬度
*
* @param pixelY
* @param zoom
* @return
*/
public static double pixelToLat(double pixelY, int zoom) {
double y = 2 * Math.PI * (1 - pixelY / (128 << zoom));
double z = Math.pow(Math.E, y);
double siny = (z - 1) / (z + 1);
return Math.asin(siny) * 180 / Math.PI;
}
}
- 大小: 21.1 KB
- 大小: 54.2 KB
- 大小: 70.3 KB
分享到:
相关推荐
标题“地图选择及地图偏移解决方案(一)”暗示了我们即将探讨的是关于地图应用开发中的一个重要主题,即如何在不同的地图平台之间进行选择,并处理地图显示时可能出现的偏移问题。这通常涉及到地理信息系统(GIS)...
百度地图偏移解决方法与高德地图偏移解决方法类似,也是基于数据库查询的方式。但是,百度地图的数据库查询规则不同于高德地图。百度地图的数据库需要保留小数点两位查询。 技术实现 要实现地图偏移解决方法,需要...
在互联网地图服务领域,为了保护自身的数据安全及防止地图数据被非法利用,许多地图服务商如Google Maps等会采用一种称为“加密偏移”(也称为坐标偏移或地图偏移)的技术手段来对公开的地图坐标进行加密处理。...
因此,针对Google和百度地图的GPS纠偏解决方案涉及到获取和应用偏移数据。对于精度为0.01的方案,大约有3000万条记录,适用于百度地图;而对于精度为0.001的高精度方案,有近9亿条记录,适用于谷歌地图,可以达到...
Google baidu 地图 gps偏移(经纬度偏移)的技术纠偏解决方案 讲解如何通过官方API实现0偏移 不要相信网上的数据库或者算法之类的,感觉都有些扯淡,并且超级影响系统性能,通过官方的解决方案更完美,更稳定
在百度、谷歌、soso、等地图上,对经纬度偏移进行正确的纠偏的最佳技术解决方案,内容包含技术解决与相关获取资料方式!
google地图经纬度偏移修正算法完美解决方案.doc
总的来说,解决矢量地图与卫星地图叠加偏移的问题需要根据具体需求选择合适的方法。方案一适合对坐标精度有较高要求的场景,而方案二则适用于注重视觉效果和叠加速度的情况。在实践中,可以根据项目特点和可用资源...
GPS偏移权威技术解决方案是中国GPS开发和互联网项目开发中不可或缺的一部分,解决了经纬度偏移问题,提高了GPS导航和地图应用的可靠性和准确性。 在国家保密插件和纠偏数据库的基础上,我们还可以提供更多的解决...
在OpenLayers 7中,集成百度地图作为瓦片图层时,可能会遇到地图显示偏移的问题。这主要是因为OpenLayers采用的是WGS84坐标系,而百度地图...这个解决方案适用于那些希望在OpenLayers项目中使用百度地图数据的开发者。
1. **SuperMap**:SuperMap是一款中国自主研发的GIS软件,提供从数据采集、处理、管理到分析、发布、共享的全套解决方案。在本项目中,SuperMap作为基础平台,提供了丰富的地图服务和二三维一体化的能力,使得用户...
在IT行业中,地图匹配是一项关键的技术,特别是在交通监控、导航系统和位置服务等领域。本项目主要涉及使用Python编程语言来处理GPS...通过深入理解这些概念和技术,可以为开发高效、准确的地图匹配解决方案提供基础。
CMaps-中国国行安卓手机使用Google地图服务解决方案
本篇文章将详细讲解如何完美解决这个问题,并提供获取已聚合点位的接口方案。 首先,我们需要了解百度地图API中的marker和label。Marker是地图上表示地理位置的图标,而label则是附加在marker上的文本,用于显示更...
在本文中,我们将深入探讨如何在Echarts 3D地图中实现数据散点下陷的效果。Echarts是一款基于JavaScript的数据可视化库,它提供了丰富的图表类型和强大的交互功能。Echarts 3D模块则进一步扩展了其能力,允许我们在...
在该项目中,`GMap.sln`是解决方案文件,包含了整个项目的所有配置和依赖。`GMap.v12.suo`和`GMap.suo`是Visual Studio的用户选项文件,存储了开发者在使用IDE时的个性化设置和调试信息。`GMap.Net`目录下是库的核心...
在Android开发中,地图是一个非常重要的功能,尤其在...通过`axisoffset.dat`、`ModifyOffset.java`和`Demo.java`这三个文件,开发者可以构建一个完整的解决方案,确保在中国境内的地图应用能够提供精确的定位服务。