首页 > 代码库 > 经纬度纠偏的一些经验
经纬度纠偏的一些经验
手机上报的经纬度,并不是所有的都是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 try100 {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 GPS51 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_offsetfrom( 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‘);
经纬度纠偏的一些经验
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。