/// <summary> /// 计算瓦片地图的行列号范围 /// </summary> /// <param name="startcoord">左下角经纬度</param> /// <param name="endcoord">右上角经纬度</param> /// <param name="z">地图层级</param> /// <returns></returns> public Tuple <int, int, int, int> GetTileBound(LatLngPoint startcoord, LatLngPoint endcoord, int z) { PointF StartMCPoint = CoordTransferHelper.LatLng2Mercator(startcoord); Point StartTilePoint = GetTileCoord(StartMCPoint, z); PointF EndPoint = CoordTransferHelper.LatLng2Mercator(endcoord); Point EndTilePoint = GetTileCoord(EndPoint, z); return(new Tuple <int, int, int, int>(StartTilePoint.X, StartTilePoint.Y, EndTilePoint.X, EndTilePoint.Y)); }
/// <summary> /// 瓦片地图拼接函数 /// 百度地图和高德地图瓦片地图组织形式不一样,用maptype加以区别 /// </summary> /// <param name="folder_list">文件夹列表</param> /// <param name="savepath">保存路径</param> /// <param name="maptype">0为百度地图,1为高德地图</param> WebApiResult <string> ParallelWriteImage(DirectoryInfo[] folder_list, String savepath, int maptype, string crstype, int maxSize) { FileInfo[] file = new FileInfo[] { }; foreach (var folder in folder_list) { FileInfo[] a = GetFileList(folder); file = JoinArray(file, a); } List <List <FileInfo> > file_list_blocks = new List <List <FileInfo> >(); deSplice(file, maxSize, ref file_list_blocks); var count = file_list_blocks.Count; //计算Total并更新 threadlog.Total = file_list_blocks.Count; new Log <BaiduTileSplicingResult>(threadlog); log.Count = threadlog.Total; new Log <BaiduTileSplicingResult>(log); //利用GDAL创建结果影像,并写入瓦片数据 Gdal.AllRegister(); //驱动注册 Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); //中文路径支持 Driver pDriver = Gdal.GetDriverByName("GTIFF"); int num = 0; //分块拼接影像 foreach (var file_list_block in file_list_blocks) { if (num < current) { num++; continue; } //if (num == 6) Pause<BaiduTileSplicingResult>(this.Result_gaode.GUID); if (maptype == 0) { if (Log <BaiduTileSplicingResult> .GetThreadLogEntity(this.Result_baidu.GUID).IsPaused) { threadlog.Current = current; threadlog.Status = "暂停"; threadlog.TStatus = 4; threadlog.IsPaused = true; new Log <BaiduTileSplicingResult>(threadlog); log.Status = "未完成"; log.Current = current; new Log <BaiduTileSplicingResult>(log); return(null); } } else { if (Log <BaiduTileSplicingResult> .GetThreadLogEntity(this.Result_gaode.GUID).IsPaused) { threadlog.Current = current; threadlog.Status = "暂停"; threadlog.TStatus = 4; threadlog.IsPaused = true; new Log <BaiduTileSplicingResult>(threadlog); log.Status = "未完成"; log.Current = current; new Log <BaiduTileSplicingResult>(log); return(null); } } FileInfo[] file_list_array = file_list_block.ToArray <FileInfo>(); if (file_list_array.Length > 1) { //获取分块的坐标信息和范围信息 List <Point> TilePoints = GetTileCoor(file_list_array); Tuple <int, int, int, int> TileBoundary = GetBoundary(TilePoints); //定义存储文件名 string level = file_list_block[0].DirectoryName.Substring(0, file_list_block[0].DirectoryName.LastIndexOf("\\")).Split('$')[0]; level = level.Substring(level.LastIndexOf("\\")); string savedir = savepath + level; //判断存储路径是否存在 if (!Directory.Exists(savedir)) { Directory.CreateDirectory(savedir); } string dstPath = savedir + '\\' + file_list_block.First <FileInfo>().DirectoryName.Split('\\').Last() + "-" + file_list_block.First <FileInfo>().Name.Split('.').First() + "_" + file_list_block.Last <FileInfo>().DirectoryName.Split('\\').Last() + "-" + file_list_block.Last <FileInfo>().Name.Split('.').First() + ".tif"; if (File.Exists(dstPath)) { continue; } string tfwPath = savedir + '\\' + file_list_block.First <FileInfo>().DirectoryName.Split('\\').Last() + "-" + file_list_block.First <FileInfo>().Name.Split('.').First() + "_" + file_list_block.Last <FileInfo>().DirectoryName.Split('\\').Last() + "-" + file_list_block.Last <FileInfo>().Name.Split('.').First() + ".tfw"; if (File.Exists(tfwPath)) { continue; } //计算图像的宽度和高度,定义图像的Dataset int bufWidth = (TileBoundary.Item3 - TileBoundary.Item1 + 1) * 256; int bufHeight = (TileBoundary.Item4 - TileBoundary.Item2 + 1) * 256; Dataset dstDataset = pDriver.Create(dstPath, bufWidth, bufHeight, 3, DataType.GDT_Byte, new String[] { "BIGTIFF=IF_NEEDED" }); //生成.tfw文件 StreamWriter writer = new StreamWriter(new FileStream(tfwPath, FileMode.Create, FileAccess.Write), Encoding.ASCII); if (maptype == 0) { int z = int.Parse(level.Substring(1)); //计算瓦片地图左上角墨卡托坐标 double mcx = TileBoundary.Item1 * 256 * Math.Pow(2, (18 - z)); double mcy = (TileBoundary.Item4 + 1) * 256 * Math.Pow(2, (18 - z)); double sizex = 256 * Math.Pow(2, (18 - z)); double sizey = sizex; if (crstype == "BD09") { var F = CoordTransferHelper.Mercator2LatLng(new PointF((float)mcx, (float)mcy)); mcx = F.Lat; mcy = F.Lng; double r1 = (TileBoundary.Item3 + 1) * 256 * Math.Pow(2, (18 - z)); double r2 = TileBoundary.Item2 * 256 * Math.Pow(2, (18 - z)); F = CoordTransferHelper.Mercator2LatLng(new PointF((float)r1, (float)r2)); sizex = Math.Abs(mcx - F.Lat) / (TileBoundary.Item3 - TileBoundary.Item1 + 1); sizey = Math.Abs(mcy - F.Lng) / (TileBoundary.Item4 - TileBoundary.Item2 + 1); } writer.WriteLine(sizex); writer.WriteLine(0.000000); writer.WriteLine(0.000000); writer.WriteLine(-1 * sizey); writer.WriteLine(mcx); writer.WriteLine(mcy); } if (maptype == 1) { int z = int.Parse(level.Substring(1)); Point TileP = new Point(TileBoundary.Item1, TileBoundary.Item2); Point PixelP = new Point(0, 0); var P = CoordTransferHelper.PixelXY2LatLng(TileP, PixelP, z); double mcx = P.Lat; double mcy = P.Lng; P = CoordTransferHelper.PixelXY2LatLng(new Point(TileBoundary.Item3, TileBoundary.Item4), new Point(256, 256), z); double sizex = Math.Abs(mcx - P.Lat) / (TileBoundary.Item3 - TileBoundary.Item1 + 1); double sizey = Math.Abs(mcy - P.Lng) / (TileBoundary.Item4 - TileBoundary.Item2 + 1); writer.WriteLine(sizex); writer.WriteLine(0.000000); writer.WriteLine(0.000000); writer.WriteLine(sizey); writer.WriteLine(mcx); writer.WriteLine(mcy); } writer.Close(); //遍历分块列表中所有影像,读取瓦片图像信息写入分块影像 for (int i = 0; i < file_list_array.Length; i++) { //打开瓦片地图,获取瓦片地图的宽度、高度、波段、位数信息 Dataset img = Gdal.Open(file_list_array[i].FullName, Access.GA_ReadOnly); int Width = img.RasterXSize; int Height = img.RasterYSize; int BandNum = img.RasterCount; int Depth = Gdal.GetDataTypeSize(img.GetRasterBand(1).DataType); //读取瓦片地图的数据信息 Byte[] buf = new Byte[Width * Height * BandNum]; CPLErr err = img.ReadRaster(0, 0, Width, Height, buf, Width, Height, BandNum, null, 0, 0, 0); if (err == CPLErr.CE_Failure) { string message = string.Format("{0}图像读取失败!", file_list_array[i].Name); return(new WebApiResult <string>() { success = 1, msg = message }); } //获取瓦片地图在拼接影像中的起始坐标信息 int OrgX = -9999, OrgY = -9999; if (maptype == 0) { OrgX = (TilePoints[i].X - TileBoundary.Item1) * 256; OrgY = (TileBoundary.Item4 - TilePoints[i].Y) * 256; } else if (maptype == 1) { OrgX = (TilePoints[i].X - TileBoundary.Item1) * 256; OrgY = (TilePoints[i].Y - TileBoundary.Item2) * 256; } if (OrgX == -9999 || OrgY == -9999) { return new WebApiResult <string>() { success = 1, msg = "坐标错误" } } ;; err = dstDataset.WriteRaster(OrgX, OrgY, Width, Height, buf, Width, Height, BandNum, null, 0, 0, 0); if (err == CPLErr.CE_Failure) { string message = string.Format("结果图像{0}输出数据失败!", file_list_block.First <FileInfo>().Name + "_" + file_list_block.Last <FileInfo>().Name + ".tif"); return(new WebApiResult <string>() { success = 1, msg = message }); } img.Dispose(); } dstDataset.Dispose(); } else { //定义存储文件名 string level = file_list_block[0].DirectoryName.Substring(0, file_list_block[0].DirectoryName.LastIndexOf("\\")).Split('_')[0]; level = level.Substring(level.LastIndexOf("\\")); string savedir = savepath + level; //判断存储路径是否存在 if (!Directory.Exists(savedir)) { Directory.CreateDirectory(savedir); } string dstPath = savedir + '\\' + file_list_block.First <FileInfo>().DirectoryName.Split('\\').Last() + "-" + file_list_block.First <FileInfo>().Name.Split('.').First() + "_" + file_list_block.Last <FileInfo>().DirectoryName.Split('\\').Last() + "-" + file_list_block.Last <FileInfo>().Name.Split('.').First() + ".tif"; if (File.Exists(dstPath)) { continue; } File.Copy(file_list_array[0].FullName.ToString(), dstPath); } current++; num++; if (maptype == 0) { threadlog = Log <BaiduTileSplicingResult> .GetThreadLogEntity(this.Result_baidu.GUID); } else { threadlog = Log <BaiduTileSplicingResult> .GetThreadLogEntity(this.Result_gaode.GUID); } threadlog.Current = current; new Log <BaiduTileSplicingResult>(threadlog); } pDriver.Deregister(); Gdal.GDALDestroyDriverManager(); return(new WebApiResult <string>() { success = 1, msg = "瓦片拼接完成!" }); }