zoukankan      html  css  js  c++  java
  • 高德离线地图瓦片坐标偏移纠偏

    对于地图坐标偏移,以leaflet为例,有如下解决办法

    方法1、修改leaflet源码,解决地图坐标偏移问题

    方法2、将点位真实的经纬度经过偏移算法,添加到加密的地图上

    方法3、直接对离线地图瓦片进行纠偏

    方法1需要修改源码

    方法2有缺陷,地图依然是偏移的,如果把地图经纬度显示出来,经纬度也是不对的

    我使用的是方法3,原理是:虽然偏移不是线性的,我也不知道纠偏算法,但是在市级或者县级区域,偏移近似线性的,所以对于市级或县级地图应用,可以对地图瓦片进行简单的纠编,优点是得到的地图瓦片可以认为是没有偏移的。

    我用C#写了一个高德地图瓦片纠偏程序,代码如下:

    1、配置文件

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
      <appSettings>
        <add key="inputPath" value="D:\_临时文件GISMap1818940751"/>
        <add key="outputPath" value="D:\_临时文件GISMapOutput1818940751"/>
        <add key="deltaPixcelX" value="1031"/>
        <add key="deltaPixcelY" value="421"/>
        <add key="fromMapZoom" value="1"/>
        <add key="toMapZoom" value="16"/>
      </appSettings>
    </configuration>
    View Code

    deltaPixcelX和deltaPixcelY根据不同城市而不同,单位是像素,在太乐地图下载器上,开启网络,放大到18级,使用下载器的纠偏计算,定位点位和纠偏后的点位,基本用眼可以看出来,差一个格就是256像素,不足一格的自己算一下,就把deltaPixcelX和deltaPixcelY参数算出来了。

    2、纠偏代码

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Configuration;
    using System.Data;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Utils;
    
    namespace TileProcess
    {
        public partial class Form1 : Form
        {
            private int _count = 0;
            private int _deltaPixcelX;
            private int _deltaPixcelY;
            private string _inputPath;
            private string _outputPath;
            private int _fromMapZoom;
            private int _toMapZoom;
    
            private DateTime _startTime;
            private int _lastCount;
    
            private 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"]);
            }
    
            private void btnTileProcess_Click(object 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 > 0)
                            {
                                lblSpeed.Text = string.Format("当前速度:{0} 张/每秒,平均速度:{1} 张/每秒", (_count - _lastCount) * 1000.0 / sleepInterval, avg);
                            }
                            _lastCount = _count;
                        }));
                    }
                }));
                thread.IsBackground = true;
                thread.Start();
            }
    
            /// <summary>
            /// 瓦片纠偏处理
            /// </summary>
            private void Process()
            {
                _startTime = DateTime.Now;
                Regex regex = new Regex(@"\(d+)\(d+).png", RegexOptions.IgnoreCase);
                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(2, 18 - i)));
    
                    string[] fileArr = Directory.GetFiles(_inputPath + "\" + i, "*.*", SearchOption.AllDirectories);
                    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(string.Format(@"{0}{1}{2}{3}.png", _outputPath, d.I, x, y));
                                if (!File.Exists(pathTarget))
                                {
                                    if (!Directory.Exists(Path.GetDirectoryName(pathTarget)))
                                    {
                                        Directory.CreateDirectory(Path.GetDirectoryName(pathTarget));
                                    }
                                    Bitmap bmpNew = new Bitmap(256, 256, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                                    bmpNew.SetResolution(96, 96);
                                    Graphics graph = Graphics.FromImage(bmpNew);
    
                                    int deltaX = data.DeltaPixcelX / 256;
                                    int deltaY = data.DeltaPixcelY / 256;
    
                                    //临时变量定义
                                    string pathSource = null;
                                    FileStream fs = null;
                                    byte[] bArr = null;
                                    MemoryStream ms = null;
                                    Bitmap bmpSource = null;
    
                                    //起始
                                    pathSource = string.Format(@"{0}{1}{2}{3}.png", _inputPath, d.I, x + deltaX, y + deltaY);
                                    if (File.Exists(pathSource))
                                    {
                                        fs = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
                                        bArr = new byte[fs.Length];
                                        int readCount = fs.Read(bArr, 0, bArr.Length);
                                        ms = new MemoryStream(bArr, 0, readCount);
                                        bmpSource = new Bitmap(ms);
                                        bmpSource.SetResolution(96, 96);
                                        graph.DrawImage(bmpSource, 0, 0, new RectangleF(data.DeltaPixcelX % 256, data.DeltaPixcelY % 256, 256 - data.DeltaPixcelX % 256, 256 - data.DeltaPixcelY % 256), GraphicsUnit.Pixel);
                                        graph.Flush();
    
                                        fs.Close();
                                        fs = null;
                                        ms.Close();
                                        ms = null;
                                        bmpSource.Dispose();
                                        bmpSource = null;
                                    }
    
                                    //
                                    pathSource = string.Format(@"{0}{1}{2}{3}.png", _inputPath, d.I, x + deltaX + 1, y + deltaY);
                                    if (File.Exists(pathSource) && (data.DeltaPixcelX > 0 || data.DeltaPixcelY > 0))
                                    {
                                        fs = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
                                        bArr = new byte[fs.Length];
                                        int readCount = fs.Read(bArr, 0, bArr.Length);
                                        ms = new MemoryStream(bArr, 0, readCount);
                                        bmpSource = new Bitmap(ms);
                                        bmpSource.SetResolution(96, 96);
                                        graph.DrawImage(bmpSource, 256 - data.DeltaPixcelX % 256, 0, new RectangleF(0, data.DeltaPixcelY % 256, data.DeltaPixcelX % 256, 256 - data.DeltaPixcelY % 256), GraphicsUnit.Pixel);
                                        graph.Flush();
    
                                        fs.Close();
                                        fs = null;
                                        ms.Close();
                                        ms = null;
                                        bmpSource.Dispose();
                                        bmpSource = null;
                                    }
    
                                    //
                                    pathSource = string.Format(@"{0}{1}{2}{3}.png", _inputPath, d.I, x + deltaX, y + deltaY + 1);
                                    if (File.Exists(pathSource) && (data.DeltaPixcelX > 0 || data.DeltaPixcelY > 0))
                                    {
                                        fs = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
                                        bArr = new byte[fs.Length];
                                        int readCount = fs.Read(bArr, 0, bArr.Length);
                                        ms = new MemoryStream(bArr, 0, readCount);
                                        bmpSource = new Bitmap(ms);
                                        bmpSource.SetResolution(96, 96);
                                        graph.DrawImage(bmpSource, 0, 256 - data.DeltaPixcelY % 256, new RectangleF(data.DeltaPixcelX % 256, 0, 256 - data.DeltaPixcelX % 256, data.DeltaPixcelY % 256), GraphicsUnit.Pixel);
                                        graph.Flush();
    
                                        fs.Close();
                                        fs = null;
                                        ms.Close();
                                        ms = null;
                                        bmpSource.Dispose();
                                        bmpSource = null;
                                    }
    
                                    //右下
                                    pathSource = string.Format(@"{0}{1}{2}{3}.png", _inputPath, d.I, x + deltaX + 1, y + deltaY + 1);
                                    if (File.Exists(pathSource) && (data.DeltaPixcelX > 0 || data.DeltaPixcelY > 0))
                                    {
                                        fs = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
                                        bArr = new byte[fs.Length];
                                        int readCount = fs.Read(bArr, 0, bArr.Length);
                                        ms = new MemoryStream(bArr, 0, readCount);
                                        bmpSource = new Bitmap(ms);
                                        bmpSource.SetResolution(96, 96);
                                        graph.DrawImage(bmpSource, 256 - data.DeltaPixcelX % 256, 256 - data.DeltaPixcelY % 256, new RectangleF(0, 0, data.DeltaPixcelX % 256, data.DeltaPixcelY % 256), GraphicsUnit.Pixel);
                                        graph.Flush();
    
                                        fs.Close();
                                        fs = null;
                                        ms.Close();
                                        ms = null;
                                        bmpSource.Dispose();
                                        bmpSource = null;
                                    }
    
                                    bmpNew.Save(pathTarget);
                                    //bmpNew.Save("d:\_临时文件\1234.png"); //测试用
    
                                    bmpNew.Dispose();
                                    bmpNew = null;
                                    graph.Dispose();
                                    graph = null;
                                } //end if (!File.Exists(pathTarget))
    
                                lock (_lock)
                                {
                                    _count++;
                                }
                            } //end if (match.Success)
                        }, data, (ex) =>
                        {
                            this.BeginInvoke(new Action(() =>
                            {
                                lblErrorMsg.Text = "出错:" + ex.Message + "
    " + ex.StackTrace;
                                LogUtil.LogError(ex, "出错");
                            }));
                        }); //end ThreadUtil.Run
                    } //end foreach (string file in fileArr)
                } //end for (int i = _fromMapZoom; i <= _toMapZoom; i++)
            }
    
        }
    }
    View Code

    辅助类ThreadUtil:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace Utils
    {
        /// <summary>
        /// 线程工具类
        /// </summary>
        public class ThreadUtil
        {
            /// <summary>
            /// 使用的逻辑处理器数
            /// </summary>
            private static int _ProcessorCount;
            private static Semaphore _semaphore;
            private static List<Task> _TaskList = new List<Task>();
            private static object _lock = new object();
    
            static ThreadUtil()
            {
                _ProcessorCount = Environment.ProcessorCount * 2 / 4; //使用的逻辑处理器数
                if (_ProcessorCount < 1) _ProcessorCount = 1;
                _semaphore = new Semaphore(_ProcessorCount, _ProcessorCount);
            }
    
            public static void Run(Action<object> doWork, object arg, Action<Exception> errorAction)
            {
                Task task = null;
                task = Task.Factory.StartNew((obj) =>
                {
                    _semaphore.WaitOne();
    
                    try
                    {
                        doWork(obj);
                    }
                    catch (Exception ex)
                    {
                        errorAction(ex);
                    }
    
                    _semaphore.Release();
    
                    lock (_lock)
                    {
                        _TaskList.Remove(task);
                    }
                }, arg);
    
                lock (_lock)
                {
                    _TaskList.Add(task);
                }
            }
    
            public static void WaitAll()
            {
                Task.WaitAll(_TaskList.ToArray());
            }
        }
    }
    View Code

    辅助类ThreadData:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace TileProcess
    {
        public class ThreadData
        {
            public int I { get; set; }
            public string File { get; set; }
            public int DeltaPixcelX { get; set; }
            public int DeltaPixcelY { get; set; }
        }
    }
    View Code

    写日志工具类就不贴了,可以用其它日志工具代替

    处理速度大约每称300张瓦片,具体根据电脑性能不同,一个城市的瓦片大约1个小时左右能处理完。

    纠偏后的地图做最佳路径分析,显示的路径和道路基本吻合,略有误差。

  • 相关阅读:
    ubuntu安装后做得几件事情 【robby_chan】
    malloc函数的一种简单的原理性实现[转]
    了解B树 B+树
    win下格式转为utf8 编码 转码
    log4j2与slf4j日志桥接
    java获取当前行数
    java获取服务器ip地址解决linux上为127.0.0.1的问题
    log4j2的基本使用
    navicator使用之mysql
    log4j与log4j2日志文件的操作
  • 原文地址:https://www.cnblogs.com/s0611163/p/12034779.html
Copyright © 2011-2022 走看看