经纬度纠偏的一些经验

  手机上报的经纬度,并不是所有的都是GPS格式的,有的是GCJ02、有的是Baidu等等,那么如何才能针对一个城市的数据进行全面的纠偏呢?首先需要建立一个纠偏库,之后使用纠偏库实现纠偏。

  以GCJ02纠偏库需要以下步骤:

  • 一、建立纠GCJ02纠偏为GPS的偏库

1)选择一个城市的范围,找到最大最小经度、纬度的范围,设置需要纠偏的精确度,比如我选择A城市做为示例设置其纠偏范围

double leftUpLng = 121.0127;
double leftUpLat = 31.0850;
double rightDownLng = 121.392234;
double rightDownLat = 31.446334;

精确度:0.0001(以米为单位)

 long lngOffsetScope = (long)((rightDownLng - leftUpLng) / 0.0001);
 long latOffsetScope = (long)((rightDownLat - leftUpLat) / 0.0001);

3)选纠偏函数

  1         private void DoOffset(List<LatLngOffsetStruct> items)
  2         {
  3             string lats = string.Join(";", items.Select(m => m.GCJ02Lat).ToArray());
  4             string lngs = string.Join(";", items.Select(m => m.GCJ02Lng).ToArray());
  5
  6             /**
  7 批量纠偏接口(POST)
  8 接口地址 http://api.zdoz.net/transmore.ashx
  9 接口说明
 10 批量纠偏,一次最大可纠偏1000个坐标点
 11 参数
 12 lats:维度,多个维度用“;”隔开
 13 lngs:经度,多个经度用“;”隔开(要注意经纬度个数相等)
 14 type:转换类型 【1.WGS -> GCJ】 【2.GCJ -> WGS】 【3.GCJ -> BD】 【4.BD -> GCJ】 【5.WGS -> BD】 【6.BD -> WGS】
 15 返回值JSON
 16 根据次序返回一个json格式的数组
 17 演示
 18 参数:lats=34.123;34.332;55.231&lngs=113.123;112.213;115.321&type=1
 19
 20 返回:[{"Lng":113.12942937312582,"Lat":34.121761850760855},{"Lng":112.21911710957568,"Lat":34.3306763095054}, {"Lng":115.33036232125529,"Lat":55.232930158541052}]
 21 */
 22             string requestUri = "http://api.zdoz.net/transmore.ashx";
 23             string parameter = string.Format("lats={0}&lngs={1}&type=2", lats, lngs);
 24             int cursor = 0;
 25
 26             GOTO_AGAIN:
 27             try
 28             {
 29                 cursor++;
 30
 31                 string httpContext = GetRequesetContext(requestUri, parameter);
 32                 // 返回:[{"Lng":113.12942937312582,"Lat":34.121761850760855},{"Lng":112.21911710957568,"Lat":34.3306763095054}, {"Lng":115.33036232125529,"Lat":55.232930158541052}]
 33                 string[] splitItems = httpContext.Split(new string[] { "[", "},{", "]" }, StringSplitOptions.RemoveEmptyEntries);
 34
 35                 if (splitItems.Length < items.Count)
 36                 {
 37                     logger.Warn("出现拆分出的lat,lng的组合长度不够" + items.Count + "!!!");
 38                 }
 39
 40                 int itemsNumber = splitItems.Length;
 41                 if (splitItems.Length > items.Count)
 42                 {
 43                     itemsNumber = items.Count;
 44                 }
 45
 46                 for (var i = 0; i < itemsNumber; i++)
 47                 {
 48                     string[] lngLat = splitItems[i].Split(new string[] { "{", "}", "\"Lng\":", ",\"Lat\":" }, StringSplitOptions.RemoveEmptyEntries);
 49                     if (lngLat.Length != 2)
 50                     {
 51                         logger.Warn("出现" + splitItems[i] + "拆分出的lat,lng格式不正确!!!");
 52                     }
 53
 54                     double lng = double.Parse(lngLat[0]);
 55                     double lat = double.Parse(lngLat[1]);
 56
 57                     LatLngOffsetStruct item = items[i];
 58                     item.GpsLng = lng;
 59                     item.GpsLat = lat;
 60                     item.LatOffset = (item.GCJ02Lat - item.GpsLat).ToString();
 61                     item.LngOffset = (item.GCJ02Lng - item.GpsLng).ToString();
 62                 }
 63             }
 64             catch (Exception ex)
 65             {
 66                 if (cursor < 5)
 67                 {
 68                     goto GOTO_AGAIN;
 69                 }
 70
 71                 logger.Error("DoOffset失败次数超过5次:\r\n{0}\r\n{1}", ex.Message, ex.StackTrace);
 72             }
 73         }
 74
 75         private string GetRequesetContext(string requestUri, string parameter)
 76         {
 77             HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
 78             request.Method = "post";
 79             request.ContentType = "application/x-www-form-urlencoded";
 80
 81             byte[] payload = System.Text.Encoding.UTF8.GetBytes(parameter);
 82             request.ContentLength = payload.Length;
 83
 84             Stream writer;
 85             try
 86             {
 87                 writer = request.GetRequestStream();
 88             }
 89             catch (Exception)
 90             {
 91                 writer = null;
 92                 Console.Write("连接服务器失败!");
 93             }
 94
 95             writer.Write(payload, 0, payload.Length);
 96             writer.Close();
 97
 98             HttpWebResponse response;
 99             try
100             {
101                 response = (HttpWebResponse)request.GetResponse();
102             }
103             catch (WebException ex)
104             {
105                 response = ex.Response as HttpWebResponse;
106             }
107
108             string httpContext = string.Empty;
109
110             using (Stream stream = response.GetResponseStream())
111             {
112                 using (StreamReader reader = new StreamReader(stream))
113                 {
114                     httpContext = reader.ReadToEnd();
115                 }
116             }
117
118             response.Close();
119
120             return httpContext;
121         }

定义纠偏结构体类:

public class LatLngOffsetStruct
{
    public double GCJ02Lng { get; set; }
    public double GCJ02Lat { get; set; }

    public double GpsLng { get; set; }
    public double GpsLat { get; set; }

    public string LngOffset { get; set; }
    public string LatOffset { get; set; }
}

4)就行纠偏的主要业务逻辑

 1         public static void main(String[] args)
 2         {
 3             double leftUpLng = 121.0127;
 4             double leftUpLat = 31.0850;
 5             double rightDownLng = 121.392234;
 6             double rightDownLat = 31.446334;
 7
 8             long lngOffsetScope = (long)((rightDownLng - leftUpLng) / 0.0001);
 9             long latOffsetScope = (long)((rightDownLat - leftUpLat) / 0.0001);
10             long totalCalculateNumbers = lngOffsetScope * latOffsetScope;
11             long cursor = 0;
12
13             int previousProgress = 0;
14             List<LatLngOffsetStruct> items = new List<LatLngOffsetStruct>();
15             List<LatLngOffsetStruct> tempitems = new List<LatLngOffsetStruct>();
16             for (double lng = leftUpLng; lng < rightDownLng; lng += 0.0001)
17             {
18                 for (double lat = leftUpLat; lat < rightDownLat; lat += 0.0001)
19                 {
20                     cursor++;
21
22                     tempitems.Add(new LatLngOffsetStruct() { GCJ02Lat = lat, GCJ02Lng = lng });
23
24                     if (tempitems.Count == 1000)
25                     {
26                         DoOffset(tempitems);                       //批量GCJ02坐标转化为GPS坐标
27
28                         items.AddRange(tempitems);
29
30                         tempitems = new List<LatLngOffsetStruct>();
31
32                         if (items.Count > 100000)
33                         {
34                             DoInsert(items);                           //批量插入纠偏结果。
35                             items = new List<LatLngOffsetStruct>();
36                         }
37                     }
38
39                     int progress = (int)(cursor * 100 / totalCalculateNumbers);
40                     if (progress > previousProgress)
41                     {
42                         previousProgress = progress;
43                         this.backgroundWorker.ReportProgress(progress, "已经开始执行进度:" + progress + "%");
44                     }
45                 }
46             }
47
48             if (tempitems.Count > 0)
49             {
50                 DoOffset(tempitems);             //纠偏GCJ02 to GPS
51                 items.AddRange(tempitems);
52                 DoInsert(items);                     //入库
53             }
54         }

5)入库函数

 1         private void DoInsert(List<LatLngOffsetStruct> tempitems)
 2         {
 3             try
 4             {
 5                 DataTable schema = new DataTable();
 6
 7                 schema.Columns.Add("GCJ02Lng", typeof(string));
 8                 schema.Columns.Add("GCJ02Lat", typeof(string));
 9                 schema.Columns.Add("LngOffset", typeof(string));
10                 schema.Columns.Add("LatOffset", typeof(string));
11
12                 foreach (var item in tempitems)
13                 {
14                     schema.Rows.Add(item.GCJ02Lng.ToString(), item.GCJ02Lat.ToString(), item.LngOffset, item.LatOffset);
15                 }
16
17                 using (SqlConnection connection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
18                 {
19                     connection.Open();
20                     using (SqlBulkCopy copy = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, null))
21                     {
22                         copy.DestinationTableName = "dbo.Global_GCJ02_LngLatOffset";
23                         copy.BatchSize = 10000;
24                         copy.BulkCopyTimeout = 12 * 60 * 60;
25
26                         copy.ColumnMappings.Clear();
27
28                         copy.ColumnMappings.Add("GCJ02Lng", "GCJ02Lng");
29                         copy.ColumnMappings.Add("GCJ02Lat", "GCJ02Lat");
30                         copy.ColumnMappings.Add("LngOffset", "LngOffset");
31                         copy.ColumnMappings.Add("LatOffset", "LatOffset");
32
33                         copy.WriteToServer(schema);
34                     }
35                 }
36             }
37             catch (Exception ex)
38             {
39                 logger.Debug("入库失败:\r\n{0}\r\n{1}", ex.Message, ex.StackTrace);
40             }
41         }

  • 二、如何使用纠偏库实现GCJ02纠偏为GPS

1)首先需要根据经验建立一个库来记录下哪些host上报的经纬度是gcj02格式的经纬度,哪些host上报的经纬度是baidu坐标的经纬度等。

create table global_gcj02_host(
    host string
);insert into global_gcj02_host(‘lbs.amap.com‘);.....
insert into global_gcj02_host(‘api.amap.com‘);
.....

2)使用host坐标系类型经验库(g_gcj02_host )、纠偏库(g_gcj02_lnglatoffset )来实现纠偏

需求:有一个库中存储的是待纠偏的数据表http_latlng

create table temp_baidu_result_for20170704 as
select t10.begintime,t10.host,t10.base_host,
    (case when isnotnull(t11.lngoffset) then (t10.longitude-t11.lngoffset) else t10.longitude end)as longitude_offset,
    (case when isnotnull(t11.latoffset) then (t10.latitude-t11.latoffset) else t10.latitude end) as latitude_offset
from
(
    select t10.begintime,t10.endtime,t10.host,t10.longitude,t10.latitude,t11.host as base_host
    from http_latlng t10 inner join g_gcj02_host as t11 on t10.host=t11.host
) t10
inner join g_gcj02_lnglatoffset t11 on rpad(t10.longitude,8,‘0‘)=rpad(t11.gcj02lng,8,‘0‘) and rpad(t10.latitude,7,‘0‘)=rpad(t11.gcj02lat,7,‘0‘);
时间: 2024-10-17 16:36:43

经纬度纠偏的一些经验的相关文章

经纬度纠偏

接口地址 http://api.zdoz.net/transmore.ashx 接口说明 批量纠偏,一次最大可纠偏1000个坐标点 参数 lats:维度,多个维度用“;”隔开 lngs:经度,多个经度用“;”隔开(要注意经纬度个数相等) type:转换类型 [1.WGS -> GCJ] [2.GCJ -> WGS] [3.GCJ -> BD] [4.BD -> GCJ] [5.WGS -> BD] [6.BD -> WGS] 返回值JSON 根据次序返回一个json格式

[转]抢先Mark!微信公众平台开发进阶篇资源集锦

FROM : http://www.csdn.net/article/2014-08-01/2820986 由CSDN和<程序员>杂志联合主办的 2014年微信开发者大会 将于8月23日在北京举行.作为一线微信开发商云集.专注在开发实践方面的顶级技术活动,演讲话题极为丰富,涵盖了微信开发不同维度的多个层内容 (首批议程发布),包括:企业服务号开发和高级应用.企业号开发.如何与业务系统对接.各种高级接口功能.智能客服与LBS.HTML5社交应用.微信支付.微信电商开发等多方面(查看 参加微信开发

android:如何从照片中获取拍摄地址信息

在开发中遇到一个需求,需要解析拿到照片拍摄时的地址信息,在网上有很多网站提供照片上传后解析出照片的具体信息,很详细.android也很给力,提供ExifInterface ,可以获取到拍摄照片时的很多信息. TAG_DATETIME 时间日期 TAG_FLASH 闪光灯 TAG_GPS_LATITUDE 纬度 TAG_GPS_LATITUDE_REF 纬度参考 TAG_GPS_LONGITUDE 经度 TAG_GPS_LONGITUDE_REF 经度参考 TAG_IMAGE_LENGTH 图片长

离线谷歌地图API的开发笔记(二)

一.地图引擎介绍 离线地图引擎运行在WINDOWS平台上,底层由Visual c++语言开发,编译为OCX插件方式.占用文件少,便于二次开发的快速安装部署. 具有专业地图的基础操作功能:地图放大.缩小.移动.测量距离,测量面积. 支持以下矢量操作:点.线.面.透明矩形.透明圆形.箭头等添加/编辑/删除操作. 软件支持操作系统:Windows98/Me/2000/XP/win7/win8/win10 支持VB,VC,Delphi,C#等开发工具的二次开发, 从此可以专注于您的专业领域,不再为地图开

openlayers3应用“三’”:百度地图坐标纠偏

前两篇文章介绍了openlayers3加载百度在线和离线瓦片地图,页面上能够正常显示.地图加载后在地图上显示一条GPS轨迹,发现离实际位置相差太远,如下图所示: 轨迹形状和实际形状相同,但是位移太远,采用坐标加偏移的方法(在原有经纬度坐标基础上进行数值增减),得到和实际轨迹完全重新的新的轨迹,如下图所示: 在地图上添加另外一条车辆轨迹,发现使用相同的坐标偏移量后,第二条轨迹又存在偏差,第二条轨迹未做偏移前如图所示: 经过坐标偏移后如下图: 可以看到地图上两条轨迹,使用相同的坐标偏移量,不能进行"

openlayers应用“三”:百度地图纠偏

前两篇文章介绍了openlayers3加载百度在线和离线瓦片地图,页面上能够正常显示.地图加载后在地图上显示一条GPS轨迹,发现离实际位置相差太远,如下图所示: 轨迹形状和实际形状相同,但是位移太远,采用坐标加偏移的方法(在原有经纬度坐标基础上进行数值增减),得到和实际轨迹完全重新的新的轨迹,如下图所示: 在地图上添加另外一条车辆轨迹,发现使用相同的坐标偏移量后,第二条轨迹又存在偏差,第二条轨迹未做偏移前如图所示: 经过坐标偏移后如下图: 可以看到地图上两条轨迹,使用相同的坐标偏移量,不能进行"

mysql经纬度查询并且计算2KM范围内附近用户的sql查询性能优化实例教程

之前很傻很天真地以为无非就是逐个计算距离,然后比较出来就行了,然后当碰到访问用户很多,而且数据库中经纬度信息很多的时候,计算量的迅速增长,能让服务器完全傻逼掉,还是老前辈的经验比我们丰富,给了我很大的启示. MySQL性能调优 – 使用更为快速的算法进行距离计算 最近遇到了一个问题,通过不断的尝试最终将某句原本占据近1秒的查询优化到了0.01秒,效率提高了100倍. 问题是这样的,有一张存放用户居住地点经纬度信息的MySQL数据表,表结构可以简化 为:id(int),longitude(long

订餐系统之按距离[根据经纬度]排序、搜索

上周六,写了第一篇博客<订餐系统之权限设计>,在此感谢那些鼓励.关注我的园友们,更要感谢那些提出宝贵建议的朋友们.看了你们的评论,才真切的感受到:朋友们的评论往往会让文章更有看点.上篇文章中 郑明.人生就是赌 等几个园友的留言让我对我们系统的权限优化有了方向.当然,这样的优化肯定不是一天两天的事,做技术的朋友应该都知道:一个难题经常啃啃,某天也许就有了好的方案了(近段时间啃掉了几个2.3年前未处理好的的问题,才想起初中数学老师让我们经常啃一些竞赛题的良苦用心),今天的文章说的就是一个从2010

ArcGIS API for JavaScript3.x 学习笔记[3] 加载底图(一)【天地图(经纬度版)】

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>天地图底图加载(经纬度版本)</title> 6 <link rel="stylesheet" href="https://js.arcgis.com/3.21/esri/css/esri.css"> 7 <script