欢迎光临
我们一直在努力

地拼接一般按什么方法,地拼接视频

获取到经纬度范围后,我们需要计算出瓦片的范围。
本文涉及的地图瓦片都以左上角为原点开始编号的,从左至右为 x 轴, 从上到下为 y轴。

为保证地图是方形,基于 Web 墨卡托投影的地图左上角经纬度坐标为(180°,85.0511 °),右下角经纬度为(-180°,-85.0511°)。纬度范围是[-85.0511, 85.0511 ]。
假设z为需要拼接的图层的层数,设n=2的z次方,lon为经度,lat为维度,则经纬度、层级和瓦片的坐标x、y的关系为:
TileX =(vps云服务器lon+180)÷360×n;
TileY = (1-(log(tan(lat))+sec(lat)))÷2×n;
在C#中,Math函数的三角参数要求为弧度,所以纬度值牵扯到三角函数的还需要×PI÷180。两个函数如下:

/// <summary> /// 计算瓦片所在X值 /// </summary> /// <param name=”lng”></param> /// <param name=”清新的香烟”></param> /// <returns></returns> public static double getTileX(double lng, int 清新的香烟) { double tileX = (lng + 180.0) / 360 * Math.Pow(2, 清新的香烟); return tileX; } /// <summary> /// 墨卡托投影下,通过维度计算瓦片所在Y值 /// </summary> /// <param name=”lat”></param> /// <param name=”清新的香烟”></param> /// <returns></returns> public static double getTileY(double lat, int 清新的香烟) { if (lat > 90) lat = lat – 180; if (lat < -90) lat = lat + 180; double tileY = Math.Pow(2, 清新的香烟) / 2 * (1 – (Math.Log(Math.Tan(Math.PI * lat / 180) + 1 / Math.Cos(Math.PI * lat / 180))) / Math.PI); return tileY; }

前面将下载图片的函数已在第三章中写好,直接通过xyz和瓦片地址下载图片,然后使用GDI+拼接即可。
这里有一个很严重的问题,就是受GDI+技术限制,图幅过大可能拼接失败。一般10000像素×10000像素以内为妥。所以,过大范围的需求,只能拼接为系统承受范围内的大小了。我们做一个参数,可以设置这个值,最大到10240像素。用户最终在ps里再量力而行的拼接了。
写一个类DownloadWork,用于在线程里展开下载任务,在构造函数中声明下载范围和下载图片的参数。
GetArea(WorkArg arg)用于对任务进行拆解,以防止GDI+内存溢出报错:

/// <summary> /// 以maxnum×maxnum为一组数据 /// </summary> /// <param name=”Arg”></param> /// <returns></returns> private List<AreaConfig> GetAreas(WorkArg Arg) { List<AreaConfig> results = new List<AreaConfig>(); for (int j = Arg.Starty, n = 0; j <= Arg.Endy; n++) { for (int i = Arg.Startx, m = 0; i <= Arg.Endx; m++) { AreaConfig area = new AreaConfig(); area.Startx = i; area.Endx = i + GlobalConfig.maxtilecount < Arg.Endx ? i + GlobalConfig.maxtilecount : Arg.Endx + 1; area.Starty = j; area.Endy = j + GlobalConfig.maxtilecount < Arg.Endy ? j + GlobalConfig.maxtilecount : Arg.Endy + 1; area.Posx = m; area.Posy = n; i += GlobalConfig.maxtilecount; results.Add(area); } j += GlobalConfig.maxtilecount; } return results; }

主下载拼接函数主要有以下任务:一是拆分任务,二是根据任务大小,创建一个bitmap,三是循环x和y下载图,并根据坐标绘制在bitmap上,四是保存bitmap到本地磁盘。其中,在三中还完成了复合图的制作,代码如下。

public void DoWork(object arg) { WorkArg Arg = (WorkArg)arg; FileInfo fInfo=new FileInfo(Arg.Filename); string savedir = “”; int xNum = (Arg.Endx – Arg.Startx + 1), yNum = (Arg.Endy – Arg.Starty + 1); int totalnum=xNum*yNum,count = 0; //受GDI的限制,每次拼图不能超过20000像素×20000像素,但实际操作过程中,远不止这个数,有时候10000像素也会出错,为了程序的稳定性, //如果设置单幅图最大不超过20×20个瓦片,就是5120×5120像素 //此处需要对数据进行拆分 List<AreaConfig> tasks = GetAreas(Arg); for (int taski = 0; taski < tasks.Count; taski++) { int xnum = tasks[taski].Endx – tasks[taski].Startx, ynum = tasks[taski].Endy – tasks[taski].Starty; Bitmap bit = new Bitmap(xnum * 256, ynum * 256); Graphics g = Graphics.FromImage(bit); for (int i = tasks[taski].Startx, m = 0; i < tasks[taski].Endx; i++, m++) { for (int j = tasks[taski].Starty, n = 0; j < tasks[taski].Endy; j++, n++) { if (!iswork) break; foreach (var url in Arg.Downloadurls) { string durl = Tools.getUrl(url, i, j, Arg.Zoom); byte[] bts = Tools.downloadTile(durl); if (bts == null) { g.DrawString(“此区域请求失败”, new Font(“宋体”, 12f), new SolidBrush(Color.Red), new Point(m * 256, n * 256)); } else { MemoryStream ms = new MemoryStream(bts); Image img = Bitmap.FromStream(ms); g.DrawImage(img, m * 256, n * 256, 256, 256); } } count++; myWorkPercent(count, totalnum,taski+1,tasks.Count); } if (!iswork) break; } string filename = fInfo.DirectoryName + “\\” + fInfo.Name + “\\”; if (!Directory.Exists(filename)) Directory.CreateDirectory(filename); savedir = filename; if (tasks.Count > 1) { filename += tasks[taski].Posy + “-” + tasks[taski].Posx + “_”; } filename+=fInfo.Name; bit.Save(filename, ImageFormat.Jpeg); g.Dispose(); bit.Dispose(); } myFinishWork(savedir); }

最后,启动线程:

public void StartWork() { iswork = true; th = new Thread(new ParameterizedThreadStart(DoWork)); th.Start(this.workarg); }

增加2个事件代理,分别传回工作状态和合并完成状态:

public delegate void Workpercent(int curnum, int maxnum, int ctasknum, int tasknum); public delegate void FinishWork(string filedir);

合并完成后,通知主界面打开任务文件夹:

void dlw_myFinishWork(string savedir) { MessageBox.Show(“任务完成!”); enableControls(true); System.Diagnostics.Process.Start(“explorer.exe”, savedir); dlw = null; }

至此,所有工作基本完成。最后在啰嗦3点:
1.最好使用天地图,占位高,不足就是每天数量有限制,可以自己申请开发者的tk,改config.txt后下载。
2.国外图只作为参考,边境问题敏感,立场要坚定,使用要谨慎。
3.软件源码会附在本文后,大家可以下载,共同研究。
链接:https://pan.baidu.com/s/1dGzf3GRY50cqmBL-oA-PGA
提取码:v77a
复制这段内容后打开百度网盘手机App,操作更方便哦
本章参考:
芒果香蕉_《地图瓦片编号与经纬度的换算关系》简书

18551883

赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。