威尼斯人线上娱乐

【威尼斯人线上娱乐】谷歌瓦片地图纠正偏差或偏向,WebGIS前端瓦片地图彰显原理及贯彻

2 4月 , 2019  

   
对谷歌(谷歌)瓦片地图进行修正,有三种艺术:一是对拼接大图进行校正,然后再一次切片;贰是直接对瓦片图实行改正。这里自身用的是第二种办法,即直接对瓦片地图举办纠正。

小说版权由作者李晓晖和博客园共有,若转发请于分明处标明出处:。

小说版权由小编李晓晖和今日头条共有,若转载请于分明处标明出处:。

  最近,有广大WebGIS开发包,ArcGIS API for
JS、OpenLayers、LeafLetjs等为我们从事WebGIS开发的人卷入了众多无敌的作用。大家很便利的行使那些库的时候,也让我们忽略了重重原理性的事物。

App.config配置:

1.背景

现阶段项目中运用百度地图、高德地图、谷歌中国地形图、天地图的须求进一步多,这里自个儿跟大家齐声对各州图使用的坐标系做二个粗略的斟酌。

1.背景

时下项目中运用百度地图、高德地图、谷歌中夏族民共和国地图、天地图的必要尤为多,那里作者跟我们齐声对外省图使用的坐标系做二个简易的追究。

譬如说,笔者事先平素在被四个题材找麻烦,正是哪些将1个点正确的显得在浏览器显示屏的不错的岗位,即经纬度坐标和荧屏坐标的转移难点。直到笔者看看壹个人民代表大会牌的博客(点击学习),里面对WebGIS的原理举办了深切的讲课。看了她的作品后平昔以为,作者写那篇小说是多余的。不过大神的稿子里面并从未详细讲解原理的代码完成。个人觉得依然很有供给通过兑现相应效能的主意领会其原理,而且落到实处时要么境遇了重重的题材,所以仍然写了那篇小说。

威尼斯人线上娱乐 1威尼斯人线上娱乐 2

二.百度地图——BD-0玖

【威尼斯人线上娱乐】谷歌瓦片地图纠正偏差或偏向,WebGIS前端瓦片地图彰显原理及贯彻。百度地图是在GCJ-0二坐标系上,又和好对坐标加密了壹回,它官方文书档案里说叫BD-0玖,如今从GPS坐标转到百度坐标有接口提供,反过来不提供。

理所当然,近来反转方法在我们其实项目中已经缓解,精确度能够完毕0.伍M之内。

贰.百度地形图——BD-0玖

百度地图是在GCJ-0二坐标系上,又团结对坐标加密了二次,它官方文书档案里说叫BD-0玖,近期从GPS坐标转到百度坐标有接口提供,反过来不提供。

当然,方今反转方法在我们实在项目中早就缓解,精确度可以直达0.五M以内。

在线地图及参数

<appSettings>
  <add key="inputPath" value="D:\_临时文件\GISMap\1818940751"/>
  <add key="outputPath" value="D:\_临时文件\GISMapOutput\1818940751"/>
  <add key="deltaPixcelX" value="1031"/>
  <add key="deltaPixcelY" value="421"/>
  <add key="fromMapZoom" value="1"/>
  <add key="toMapZoom" value="18"/>
</appSettings>

2.一百度瓦片获取思路

百度地图的阴影依旧专业的Web横轴墨卡托投影,所以其切图的坐标原点、范围都以能够总结出来的。瓦片大小、基本URL也都能够经过监听百度的U凯雷德L获取。须求小心的是,百度地图的瓦片行列号和负载地址在分裂级别上都会迥然差异,其变化规则如下:

瓦片的行列号是每增添多少个级别便会进展贰个条条框框的晃动,其偏移算法如下:

     威尼斯人线上娱乐 3                      
                     

贰.1百度瓦片获取思路

百度地图的影子依旧正式的Web横轴墨卡托投影,所以其切图的坐标原点、范围都以足以总结出来的。瓦片大小、基本URL也都足以透过监听百度的U奥迪Q7L获取。需求专注的是,百度地图的瓦片行列号和负载地址在分歧级别上都会有所分歧,其变动规则如下:

瓦片的行列号是每扩充二个级别便会进展贰个平整的舞狮,其偏移算法如下:

     威尼斯人线上娱乐 4                      
                     

 以Arcgis
online上的瓦片地图为例,服务中有几个相比较关键的利用到的参数。

View Code

贰.2本土坐标系图层与百度底图叠加的研商

二.二地面坐标系图层与百度底图叠加的探赜索隐

  • Height、Weight:各样瓦片的幅度和可观
  • Resolution:每二个缩放级别下一像素代表的地形图单位(投影坐标)
  • Initial Extent:瓦片地图的限定

对瓦片图实行更正处理的算法代码:

贰.2.一 强行对瓦片数据实行改正

在新式的arcBruTile0.七中曾经支持对百度地图的增加。能够加载了百度瓦片后,通过搜索百度地图上与地点地图上的控制点对展开强行考订。

缺点是栅格图像纠正偏差或偏向形变是很难幸免的,而且工作量也大,并且很难自动化。

二.2.一 强行对瓦片数据举行更正

在最新的arcBruTile0.7中一度支撑对百度地图的拉长。能够加载了百度瓦片后,通过查找百度地图上与本土地图上的控制点对开始展览强行改正。

缺陷是栅格图像纠正偏差或偏向形变是很难幸免的,而且工作量也大,并且很难自动化。

获取地图瓦片

威尼斯人线上娱乐 5威尼斯人线上娱乐 6

2.贰.二 将矢量数据转换为百度坐标系——以明尼阿波利斯90坐标系为例

a.获取WGS八4到西雅图90坐标系上的七参数。

b.通过确立控制点库(已研究开发),利用工具(已研究开发)将塞尔维亚Bell格莱德90坐标周详据自动转换为WGS八四坐标周密据。

c.再建立WGS84与百度坐标系之间的控制点库(已研究开发),将WGS8四数据再转移为百度坐标周到据。

d.叠加后测试。

二.2.二 将矢量数据转换为百度坐标系——以巴拿马城90坐标系为例

a.获取WGS八4到达卡90坐标系上的七参数。

b.通过创设控制点库(已研究开发),利用工具(已研究开发)将热那亚90坐标周详据自动转换为WGS八四坐标周密据。

c.再建立WGS八四与百度坐标系之间的支配点库(已研究开发),将WGS八肆数据再转换为百度坐标周密据。

d.叠加后测试。

由此观望arcgis地图的瓦片组织办法,

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
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;

        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);
                                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);
                                    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))
                                {
                                    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);
                                    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))
                                {
                                    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);
                                    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))
                                {
                                    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);
                                    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;

                                _count++;
                            } //end if (!File.Exists(pathTarget))
                        } //end if (match.Success)
                    }, data, (ex) =>
                    {
                        this.BeginInvoke(new Action(() =>
                        {
                            lblErrorMsg.Text = "出错:" + ex.Message + "\r\n" + ex.StackTrace;
                            LogUtil.LogError(ex, "出错");
                        }));
                    }); //end ThreadUtil.Run
                } //end foreach (string file in fileArr)
            } //end for (int i = _fromMapZoom; i <= _toMapZoom; i++)
        }
    }
}

贰.贰.3结实突显

                                            威尼斯人线上娱乐 7

威尼斯人线上娱乐 8

 

贰.二.三结果体现

                                            威尼斯人线上娱乐 9

威尼斯人线上娱乐 10

 

http://cache1.arcgisonline.cn/ArcGIS/rest/services/ChinaOnlineCommunityOnlyENG/MapServer/tile/缩放等级/行号/列号

View Code

三.高德地图和谷歌(Google)中中原人民共和国地形图——GCJ-0二

叁.高德地图和谷歌中中原人民共和国地图——GCJ-0二

由此python程序将毫无疑问缩放等级的瓦片保存到地面
笔者只抓取了0-伍级别的瓦片,并遵照arcgis瓦片的保留方法存款和储蓄。

处理功用:小编自个儿电脑每秒处理大约350张瓦片图,①到18级瓦片共拾0多万张图纸,大致供给处理肆拾7分钟。

叁.①地图坐标系的追究

高德地图和谷歌地图均是选取的GCJ-0贰坐标系,以下为测试例子:

 威尼斯人线上娱乐 11

具体来说GCJ-0二坐标系与WGS八4坐标系偏移1般在100M上下,那种拍卖技术,是经过一种办法将一张地图修改为别的一张地图,修改形成之后,地图上的点,会发生大到几百米,小到几10米的撼动。假若你用几何上坐标转换的秘籍想过来原地图,难度一点都不小,因为拍卖技术的拍卖映射函数是非线性的。网上有许多五个坐标之间的转换方法,可是精确度一般般,在拾M左右。

在境内,GCJ-02带来的舞狮最大有700米左右,偏移的相对值能够参考下图(最红处类似700
m,最蓝处大概 20 米):

 威尼斯人线上娱乐 12

三.1地图坐标系的切磋

高德地图和谷歌地图均是运用的GCJ-0二坐标系,以下为测试例子:

 威尼斯人线上娱乐 13

具体来说GCJ-02坐标系与WGS八四坐标系偏移一般在100M上下,那种处理技术,是透过1种艺术将一张地图修改为此外一张地图,修改完结以往,地图上的点,会产生大到几百米,小到几10米的晃动。假如您用几何上坐标转换的法子想恢复生机原地图,难度十分的大,因为处理技术的处理映射函数是非线性的。网上有无数八个坐标之间的转换方法,不过精确度一般般,在10M左右。

在境内,GCJ-0贰带来的偏移最大有700米左右,偏移的相对值能够参照下图(最红处类似700
m,最蓝处大致 20 米):

 威尼斯人线上娱乐 14

威尼斯人线上娱乐 15

瓦片图纠偏前后相比较:

叁.三地方坐标周详据叠加到GCJ-02坐标系上

三.二本地坐标周到据叠加到GCJ-0二坐标系上

威尼斯人线上娱乐 16威尼斯人线上娱乐 17

威尼斯人线上娱乐 18

三.二.一转移流程

鉴于本地数据并不会是大范围的,所以其部分偏移上得以由此线性方法临时逼近。

a.本地坐标数据转换为WGS八四坐标数据。

b.对当地WGS8肆坐标数据举行Web横轴墨卡托投影。

c.将投影后的数量叠加到高德可能谷歌(谷歌)中夏族民共和国地图上。

d.进行线性偏移。

3.2.壹转移流程

出于地方数据并不会是大范围的,所以其有个别偏移上得以由此线性方法权且逼近。

a.本地坐标数据转换为WGS八四坐标数据。

威尼斯人线上娱乐,b.对地点WGS84坐标数据开始展览Web横轴墨卡托投影。

c.将投歌后的数码叠加到高德大概谷歌(谷歌)中国地图上。

d.实行线性偏移。

# -*- coding:utf-8 -*-
import urllib2
import urllib
import os
import math
def GetPage(geturl):
    req = urllib2.Request(geturl)
    user_agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 ' \
                 '(KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
    req.add_header('User-Agent', user_agent)
    response = urllib2.urlopen(req, timeout=10)
    page = response.read()
    return page
for level in range(0,6):
    try:
        newdir = "MapTitles/"+str(level)
        os.makedirs(newdir.decode("utf-8"))
    except:
        pass
    for row in range(0,int(math.pow(2,level))):
        try:
            newdir = "MapTitles/"+str(level)+"/"+str(row)
            os.makedirs(newdir.decode("utf-8"))
        except:
            pass
        for col in range(0,int(math.pow(2,level))):
            f = open("MapTitles/"+str(level)+"/"+str(row)+"/"+str(col)+'.jpg', 'wb')
            dataurl = "http://cache1.arcgisonline.cn/ArcGIS/rest/services/ChinaOnlineCommunityOnlyENG/MapServer/tile/"+str(level)+"/"+str(row)+"/"+str(col)
            data = GetPage(dataurl)
            f.write(data)
            f.close()
            pass
        pass
    pass

 

3.二.二结果展现

 威尼斯人线上娱乐 19

叁.2.二结实体现

 威尼斯人线上娱乐 20

View Code

4.天地图——CGCS2000

4.天地图——CGCS2000

 展现页面

肆.一坐标系商量

天地图上分歧省份使用的坐标系恐怕两样,如今来看本身经手过的山东、广东均为专业的国家标准三千坐标系。不过多少地点为本地坐标系,还需测量绘制局提供保密插件举行拍卖。

国家标准两千坐标系与WGS八四坐标系偏差十分的小,因为CGCS2000坐标系与WGS八4坐标系的原点、尺度、定向及定向演化的定义都以一模一样的,参考椭球的参数略有差别而已。相同的坐标点,在CGCS三千与WGS八四下,经度是如出一辙的,只在纬度上存有0.1一mm上下的界别,能够忽略掉。

4.一坐标系研究

天地图上分裂省区使用的坐标系大概差别,近年来来看本人经手过的西藏、湖南均为正式的国家标准三千坐标系。可是有些地点为地点坐标系,还需测量绘制局提供保密插件进行处理。

国标3000坐标系与WGS八肆坐标系偏差非常的小,因为CGCS两千坐标系与WGS八四坐标系的原点、尺度、定向及定向演化的概念都以1致的,参考椭球的参数略有差别而已。相同的坐标点,在CGCS贰仟与WGS八4下,经度是平等的,只在纬度上存有0.1一mm上下的区分,能够忽略掉。

展会页面只包括多少个canvas元素作为地图容器。

四.2 当地坐标系矢量数据叠加到天地图上

a.将本地数据转换为WGS八四可能国标3000坐标周到据。

b.叠加到天地图上。

4.二 本地坐标系矢量数据叠加到天地图上

a.将本地数据转换为WGS八4仍旧国家标准3000坐标周全据。

b.叠加到天地图上。

威尼斯人线上娱乐 21威尼斯人线上娱乐 22

四.3结出体现

 威尼斯人线上娱乐 23

                                                                
 —–欢迎转发,但保留版权,请于明显处标明出处:

                                                                     
假如你认为本文确实帮忙了您,能够微信扫1扫,进行小额的打赏和鼓励,多谢^_^

                                      威尼斯人线上娱乐 24

 

4.三结出突显

 威尼斯人线上娱乐 25

                                                                
 —–欢迎转发,但保留版权,请于显著处标明出处:

                                                                     
若是你认为本文确实辅助了你,能够微信扫一扫,进行小额的打赏和鼓励,多谢^_^

                                      威尼斯人线上娱乐 26

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>显示瓦片地图</title>
</head>
<body>
<canvas width="1000px" height="700px" id="mapcv" style="margin: 10px"></canvas>
</body>
<script src="Libs/jquery-1.9.1.min.js"></script>
<script src="Scripts/config.js"></script>
<script src="Scripts/init.js"></script>
</html>

View Code

安插消息

在config.js里面保存了连带的配置新闻

 

威尼斯人线上娱乐 27威尼斯人线上娱乐 28

var MapConfig={
    RootDir:'MapTitles/',
    ViewHeight:700,
    ViewWidth:1000,
    TitlePix:256,
    Resolution:[156543.033928,78271.5169639999,39135.7584820001,19567.8792409999,
                9783.93962049996,4891.96981024998,2445.98490512499,1222.99245256249,
                611.49622628138,305.748113140558,152.874056570411,76.4370282850732,
                38.2185141425366,19.1092570712683,9.55462853563415,4.77731426794937,
                2.38865713397468,1.19432856685505],
    Scale:[ 591657527.591555,295828763.795777,147914381.897889,73957190.948944,
            36978595.474472,18489297.737236,9244648.868618,4622324.434309,2311162.217155,
            1155581.108577,577790.554289,288895.277144,144447.638572,72223.819286,
            36111.909643,18055.954822,9027.977411,4513.988705],
    FullExtent:{
        xmin : -20037507.0672,
        ymin : -20036018.7354,
        xmax : 20037507.0672,
        ymax : 20102482.4102,
        spatialReference : {
            wkid : 102100
        }
    }
};

View Code

 

效果实现 init.js

地点只是把代码列了出去,那1部分才是本人要讲的终极(才到第叁☺)

壹 明显战士的地形图中央点坐标,以及缩放级别
贰 总计当前窗口显示的地图范围

大家能够依据窗口的宗旨点坐标,窗口大小,以及当前缩放级其他Resolution能够很简单通过计算获得,当前窗口你可以看看的地形图范围。

//当前窗口显示的范围
minX=centerGeoPoint.x-(MapConfig.Resolution[level]*MapConfig.ViewWidth/2);
maxX=centerGeoPoint.x+(MapConfig.Resolution[level]*MapConfig.ViewWidth/2);
minY=centerGeoPoint.y-(MapConfig.Resolution[level]*MapConfig.ViewHeight/2);
maxY=centerGeoPoint.y+(MapConfig.Resolution[level]*MapConfig.ViewHeight/2);

此地要小心一下地图的种类号的源点在左上角,然而地图左上角的影子坐标x是非常小的,y是最大的。也就会说行列号的起源在左上角,投影坐标的源点在左下角。

三 计算左上角开端行列号

//左上角开始的行列号
leftTopTitleRow = Math.floor(Math.abs(maxY-MapConfig.FullExtent.ymax)/MapConfig.Resolution[level]/MapConfig.TitlePix);
leftTopTitleCol = Math.floor(Math.abs(minX-MapConfig.FullExtent.xmin)/MapConfig.Resolution[level]/MapConfig.TitlePix);

肆 总括实际地理范围

//实际地理范围
realMinX = MapConfig.FullExtent.xmin+leftTopTitleCol*MapConfig.TitlePix*MapConfig.Resolution[level];
realMaxY = MapConfig.FullExtent.ymax-leftTopTitleRow*MapConfig.TitlePix*MapConfig.Resolution[level];

大家都知晓,大家获得到的瓦片的限制势必是高于彰显窗口的限量。不然在窗口内突显的地图是不完整的

 

威尼斯人线上娱乐 29

五 计算左上角偏移像素

在将地图瓦片拼接到窗口内是亟需思虑到实在地理范围与展现地理范围的舞狮

//计算左上角偏移像素
offSetX = (realMinX-minX)/MapConfig.Resolution[level];
offSetY = (maxY-realMaxY)/MapConfig.Resolution[level];

6 总计瓦片个数

赢得瓦片个数后就足以依据瓦片个数以及偏移后的开首瓦片地点,将每2个瓦片拼接到canvas相应的地点上

//计算瓦片个数
xClipNum = Math.ceil((MapConfig.ViewHeight+Math.abs(offSetY))/MapConfig.TitlePix);
yClipNum = Math.ceil((MapConfig.ViewWidth+Math.abs(offSetX))/MapConfig.TitlePix);

柒 前端绘制瓦片

var mapcv = document.getElementById("mapcv");
    var myctx = mapcv.getContext("2d");
    for(var i=0;i<xClipNum;i++){
        for(var j=0;j<yClipNum;j++){
            var beauty = new Image();
            beauty.src = MapConfig.RootDir+level+"/"+(leftTopTitleRow+i)+"/"+(leftTopTitleCol+j)+".jpg";
            var TitleImg={
                img:null,
                x:0,
                y:0
            };
            TitleImg.img=beauty;
            TitleImg.x=offSetX+(j*MapConfig.TitlePix);
            TitleImg.y=offSetY+(i*MapConfig.TitlePix);
            TitlesArry.push(TitleImg);
            myctx.drawImage(TitleImg.img, TitleImg.x, TitleImg.y);
        }
    }

全体代码

中间涉及到了2个经纬度换投影坐标的函数,详情参见本身的另壹篇有关百度坐标、WGS-八4、土星坐标,以及投影坐标与经纬度的转移的小说(点击跳转)

 

威尼斯人线上娱乐 30威尼斯人线上娱乐 31

$(document).ready(function(){
    moveX = 0;
    moveY = 0;
    TitlesArry=[];
    //设置将要现实的地图中心点
    centerGeoPoint={
        x:116.337737,
        y:39.912465
    };
    centerGeoPoint=lonlatTomercator(centerGeoPoint);
    level = 5;
    //当前窗口显示的范围
    minX=centerGeoPoint.x-(MapConfig.Resolution[level]*MapConfig.ViewWidth/2);
    maxX=centerGeoPoint.x+(MapConfig.Resolution[level]*MapConfig.ViewWidth/2);
    minY=centerGeoPoint.y-(MapConfig.Resolution[level]*MapConfig.ViewHeight/2);
    maxY=centerGeoPoint.y+(MapConfig.Resolution[level]*MapConfig.ViewHeight/2);
    //左上角开始的行列号
    leftTopTitleRow = Math.floor(Math.abs(maxY-MapConfig.FullExtent.ymax)/MapConfig.Resolution[level]/MapConfig.TitlePix);
    leftTopTitleCol = Math.floor(Math.abs(minX-MapConfig.FullExtent.xmin)/MapConfig.Resolution[level]/MapConfig.TitlePix);
    //实际地理范围
    realMinX = MapConfig.FullExtent.xmin+leftTopTitleCol*MapConfig.TitlePix*MapConfig.Resolution[level];
    realMaxY = MapConfig.FullExtent.ymax-leftTopTitleRow*MapConfig.TitlePix*MapConfig.Resolution[level];

    //计算左上角偏移像素
    offSetX = (realMinX-minX)/MapConfig.Resolution[level];
    offSetY = (maxY-realMaxY)/MapConfig.Resolution[level];
    //计算瓦片个数
    xClipNum = Math.ceil((MapConfig.ViewHeight+Math.abs(offSetY))/MapConfig.TitlePix);
    yClipNum = Math.ceil((MapConfig.ViewWidth+Math.abs(offSetX))/MapConfig.TitlePix);
    //右下角行列号
    rightBottomTitleRow = leftTopTitleRow+xClipNum-1;
    rightBottomTitleCol = leftTopTitleCol+yClipNum-1;
    realMaxX = MapConfig.FullExtent.xmin+(rightBottomTitleCol+1)*MapConfig.TitlePix*MapConfig.Resolution[level];
    realMinY = MapConfig.FullExtent.ymax-(rightBottomTitleRow+1)*MapConfig.TitlePix*MapConfig.Resolution[level];
    var mapcv = document.getElementById("mapcv");
    var myctx = mapcv.getContext("2d");
    for(var i=0;i<xClipNum;i++){
        for(var j=0;j<yClipNum;j++){
            var beauty = new Image();
            beauty.src = MapConfig.RootDir+level+"/"+(leftTopTitleRow+i)+"/"+(leftTopTitleCol+j)+".jpg";
            var TitleImg={
                img:null,
                x:0,
                y:0
            };
            TitleImg.img=beauty;
            TitleImg.x=offSetX+(j*MapConfig.TitlePix);
            TitleImg.y=offSetY+(i*MapConfig.TitlePix);
            TitlesArry.push(TitleImg);
            myctx.drawImage(TitleImg.img, TitleImg.x, TitleImg.y);
        }
    }
});
function lonlatTomercator(lonlat) {
    var mercator={x:0,y:0};
    var x = lonlat.x *20037508.34/180;
    var y = Math.log(Math.tan((90+lonlat.y)*Math.PI/360))/(Math.PI/180);
    y = y *20037508.34/180;
    mercator.x = x;
    mercator.y = y;
    return mercator ;
}

View Code

 

总结

可望对WebGIS的初学者掌握瓦片地图呈现原理能有帮扶

 


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图