(地图瓦片纠偏最好的方法在这:https://www.cnblogs.com/s0611163/p/15606460.html)
对于地图坐标偏移,以leaflet为例,有如下解决办法
方法3、直接对离线地图瓦片进行纠偏
方法2有缺陷,地图依然是偏移的,如果把地图经纬度显示出来,经纬度也是不对的
我使用的是方法3,原理是:虽然偏移不是线性的,我也不知道纠偏算法,但是在市级或者县级区域,偏移近似线性的,所以对于市级或县级地图应用,可以对地图瓦片进行简单的纠编,优点是得到的地图瓦片可以认为是没有偏移的。
1、配置文件
<?xml version="1.0" encoding="utf-8" ?> <configuration> startup> supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </appSettingsadd key="inputPath" value="D:\_临时文件\GISMap\1818940751"/> ="outputPath"="D:\_临时文件\GISMapOutput\1818940751"="deltaPixcelX"="1031"="deltaPixcelY"="421"="fromMapZoom"="1"="toMapZoom"="16"> >
deltaPixcelX和deltaPixcelY根据不同城市而不同,单位是像素,在太乐地图下载器上,开启网络,放大到18级,使用下载器的纠偏计算,定位点位和纠偏后的点位,基本用眼可以看出来,差一个格就是256像素,不足一格的自己算一下,就把deltaPixcelX和deltaPixcelY参数算出来了。
2、纠偏代码
using System; System.Collections.Generic; System.ComponentModel; System.Configuration; System.Data; System.Drawing; System.Drawing.Imaging; System.IO; System.Linq; System.Text; System.Text.RegularExpressions; System.Threading; System.Threading.Tasks; System.Windows.Forms; Utils; namespace TileProcess { public partial class Form1 : Form { private int _count = 0; int _deltaPixcelX; _deltaPixcelY; string _inputPath; _outputPath; _fromMapZoom; _toMapZoom; private DateTime _startTime; _lastCount; object _lock = new object(); public Form1() { InitializeComponent(); _deltaPixcelX = Convert.ToInt32(ConfigurationManager.AppSettings["deltaPixcelX"]); _deltaPixcelY = Convert.ToInt32(ConfigurationManager.AppSettings[deltaPixcelY]); _inputPath = ConfigurationManager.AppSettings[inputPath]; _outputPath = ConfigurationManager.AppSettings[outputPath]; _fromMapZoom = Convert.ToInt32(ConfigurationManager.AppSettings[fromMapZoom]); _toMapZoom = Convert.ToInt32(ConfigurationManager.AppSettings[toMapZoom]); } void btnTileProcess_Click( sender,EventArgs e) { this.btnTileProcess.Enabled = false; Task.Factory.StartNew(() => { LogUtil.Log(开始处理); Process(); }); Thread thread = new Thread(new ThreadStart(() => { int sleepInterval = 1000; while (true) { Thread.Sleep(sleepInterval); this.BeginInvoke(new Action(() => { double totalSeconds = DateTime.Now.Subtract(_startTime).TotalSeconds; int avg = (int)(_count / totalSeconds); lblMsg.Text = string.Format(已处理 {0} 张瓦片图,_count); if (_count - _lastCount > ) { lblSpeed.Text = 当前速度:{0} 张/每秒,平均速度:{1} 张/每秒",(_count - _lastCount) * 1000.0 / sleepInterval,avg); } _lastCount = _count; })); } })); thread.IsBackground = ; thread.Start(); } /// <summary> /// 瓦片纠偏处理 </summary> void Process() { _startTime = DateTime.Now; Regex regex = new Regex(@"\\(\d+)\\(\d+).pngnoreCase); for (int i = _fromMapZoom; i <= _toMapZoom; i++) { int deltaPixcelX = (int)Math.Round(_deltaPixcelX / Math.Round(Math.Pow(2,18 - i))); int deltaPixcelY = (int)Math.Round(_deltaPixcelY / Math.Round(Math.Pow( i))); string[] fileArr = Directory.GetFiles(_inputPath + \\" + i,1)">*.*foreach (string file in fileArr) { ThreadData data = new ThreadData(); data.File = file; data.I = i; data.DeltaPixcelX = deltaPixcelX; data.DeltaPixcelY = deltaPixcelY; ThreadUtil.Run((obj) => { ThreadData d = obj as ThreadData; Match match = regex.Match(d.File); if (match.Success) { int x = Convert.ToInt32(match.Groups[1].Value); int y = Convert.ToInt32(match.Groups[2].Value); string pathTarget = string.Format({0}\{1}\{2}\{3}.pngif (!File.Exists(pathTarget)) { Directory.Exists(Path.GetDirectoryName(pathTarget))) { Directory.CreateDirectory(Path.GetDirectoryName(pathTarget)); } Bitmap bmpNew = new Bitmap(256,1)">256stem.Drawing.Imaging.PixelFormat.Format32bppArgb); bmpNew.SetResolution(96,1)">96); Graphics graph = Graphics.FromImage(bmpNew); int deltaX = data.DeltaPixcelX / ; int deltaY = data.DeltaPixcelY / ; //临时变量定义 string pathSource = null; FileStream fs = byte[] bArr = ; MemoryStream ms = ; Bitmap bmpSource = 起始 pathSource = deltaY); (File.Exists(pathSource)) { fs = FileStream(pathSource,FileMode.Open,FileAccess.Read); bArr = byte[fs.Length]; int readCount = fs.Read(bArr,bArr.Length); ms = new MemoryStream(bArr,readCount); bmpSource = Bitmap(ms); bmpSource.SetResolution(); graph.DrawImage(bmpSource,0,new RectangleF(data.DeltaPixcelX % 256 - data.DeltaPixcelX % 256 - data.DeltaPixcelY % ),GraphicsUnit.Pixel); graph.Flush(); fs.Close(); fs = ; ms.Close(); ms = ; bmpSource.dispose(); bmpSource = ; } 右 pathSource = 1,1)">if (File.Exists(pathSource) && (data.DeltaPixcelX > 0 || data.DeltaPixcelY > )) { fs = new RectangleF(下 pathSource = ); 右下 pathSource = ; } bmpNew.Save(pathTarget); bmpNew.Save("d:\\_临时文件\\1234.png"); 测试用 bmpNew.dispose(); bmpNew = ; graph.dispose(); graph = ; } end if (!File.Exists(pathTarget)) lock (_lock) { _count++; } } end if (match.Success) },data,(ex) => { lblErrorMsg.Text = 出错:" + ex.Message + \r\n" + ex.StackTrace; LogUtil.LogError(ex,1)">出错); })); }); end ThreadUtil.Run } end foreach (string file in fileArr) } end for (int i = _fromMapZoom; i <= _toMapZoom; i++) } } }
辅助类ThreadUtil:
System.Threading.Tasks; Utils { <summary> 线程工具类 </summary> ThreadUtil { 使用的逻辑处理器数 static _ProcessorCount; static Semaphore _semaphore; static List<Task> _TaskList = new List<Task>(); ThreadUtil() { _ProcessorCount = Environment.ProcessorCount * 2 / 4; 使用的逻辑处理器数 if (_ProcessorCount < 1) _ProcessorCount = ; _semaphore = Semaphore(_ProcessorCount,_ProcessorCount); } void Run(Action<object> doWork,1)">object arg,Action<Exception> errorAction) { Task task = ; task = Task.Factory.StartNew((obj) => { _semaphore.WaitOne(); try { doWork(obj); } catch (Exception ex) { errorAction(ex); } _semaphore.Release(); (_lock) { _TaskList.Remove(task); } },arg); (_lock) { _TaskList.Add(task); } } WaitAll() { Task.WaitAll(_TaskList.ToArray()); } } }
辅助类ThreadData:
ThreadData { int I { get; set; } string File { int DeltaPixcelX { int DeltaPixcelY { ; } } }
处理速度大约每称300张瓦片,具体根据电脑性能不同,一个城市的瓦片大约1个小时左右能处理完。
纠偏后的地图做最佳路径分析,显示的路径和道路基本吻合,略有误差。
还有另一种纠偏方法,通过修改leaflet源码进行纠偏:https://www.cnblogs.com/s0611163/p/13396622.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。