You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1602 lines
59 KiB
1602 lines
59 KiB
using OSGeo.GDAL; |
|
using OSGeo.OGR; |
|
using OSGeo.OSR; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Data.SQLite; |
|
using System.Drawing; |
|
using System.Drawing.Imaging; |
|
using System.IO; |
|
using System.Linq; |
|
using System.Runtime.InteropServices; |
|
using System.Text; |
|
using System.Threading; |
|
using System.Threading.Tasks; |
|
using System.Windows.Forms; |
|
|
|
namespace Kingo.Plugin.RasterToKOTilesApp.KoDataBase |
|
{ |
|
|
|
|
|
public class RasterInfo : IDisposable |
|
{ |
|
public string Projection { get; private set; } |
|
public Dataset Dataset { get; private set; } |
|
public int XSize { get; set; } |
|
public int YSize { get; set; } |
|
public double TransScale { get; set; } |
|
|
|
public Envelope Extent { get; set; } |
|
public double[] Geotransform { get; private set; } |
|
public int Bands { get; private set; } |
|
|
|
private RasterInfo() { } |
|
public static RasterInfo Create(string fileName) |
|
{ |
|
try |
|
{ |
|
//消除中文路径无法识别的问题 |
|
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); |
|
Dataset dataset = Gdal.Open(fileName, Access.GA_ReadOnly); |
|
return Create(dataset); |
|
} |
|
catch (Exception ex) |
|
{ |
|
return null; |
|
} |
|
} |
|
public static RasterInfo Create(Dataset dataset) |
|
{ |
|
RasterInfo pRasterInfo = new RasterInfo(); |
|
pRasterInfo.Dataset = dataset; |
|
pRasterInfo.XSize = pRasterInfo.Dataset.RasterXSize; |
|
pRasterInfo.YSize = pRasterInfo.Dataset.RasterYSize; |
|
pRasterInfo.Geotransform = new double[6]; |
|
pRasterInfo.Dataset.GetGeoTransform(pRasterInfo.Geotransform); |
|
double north = pRasterInfo.Geotransform[3]; |
|
double south = pRasterInfo.Geotransform[3] + pRasterInfo.Geotransform[5] * pRasterInfo.YSize; |
|
double east = pRasterInfo.Geotransform[0] + pRasterInfo.Geotransform[1] * pRasterInfo.XSize; |
|
double west = pRasterInfo.Geotransform[0]; |
|
if (Math.Round(pRasterInfo.Geotransform[1] + pRasterInfo.Geotransform[5], 1) != 0) |
|
throw new Exception("栅格对象被压缩"); |
|
pRasterInfo.TransScale = pRasterInfo.Geotransform[1]; |
|
pRasterInfo.Bands = pRasterInfo.Dataset.RasterCount; |
|
//this.ScaleY = geotransform[5]; |
|
pRasterInfo.Projection = pRasterInfo.Dataset.GetProjection(); |
|
pRasterInfo.Extent = new Envelope() |
|
{ |
|
XMax = east, |
|
XMin = west, |
|
YMax = north, |
|
YMin = south |
|
}; |
|
return pRasterInfo; |
|
} |
|
public void Dispose() |
|
{ |
|
Dataset.Dispose(); |
|
} |
|
} |
|
|
|
public delegate List<TileInfo> CompareTileInfo(List<TileInfo> tileInfos); |
|
public class MultRaster2MBTiles |
|
{ |
|
static MultRaster2MBTiles() |
|
{ |
|
} |
|
|
|
public ImageFormat ImgFormat { get; set; } |
|
public int Level { get; set; } |
|
|
|
|
|
public Layer TopLayer { get; set; } |
|
private List<RasterInfo> Rasters = new List<RasterInfo>(); |
|
|
|
private Dataset topRasterDs = null; |
|
|
|
private RasterInfo topRaster = null; |
|
|
|
public int CompressRate { get; set; } = 25; |
|
|
|
/// <summary> |
|
/// 相交 |
|
/// </summary> |
|
public event CompareTileInfo CompareIntersect = null; |
|
|
|
|
|
public EnumSaveType SaveType { get; set; } |
|
|
|
|
|
public void Dispose() |
|
{ |
|
if (topRasterDs != null) |
|
topRasterDs.Dispose(); |
|
if (topRaster != null) |
|
topRaster.Dispose(); |
|
} |
|
|
|
public MultRaster2MBTiles() |
|
{ |
|
//Rasters = new List<RasterInfo>(); |
|
//codecInfo = GetEncoder(ImageFormat.Png); |
|
//System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality; |
|
//EncoderParameters myEncoderParameters = new EncoderParameters(1); |
|
//EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder,8); |
|
//myEncoderParameters.Param[0] = myEncoderParameter; |
|
//encoderParameters = myEncoderParameters; |
|
ImgFormat = ImageFormat.Jpeg; |
|
} |
|
|
|
private Envelope rasterExtent; |
|
|
|
public int TiledSize { get; set; } |
|
|
|
|
|
public string MBTilesPath { get; set; } |
|
|
|
private List<TileInfo> GetAllTiles(Envelope extent, Envelope envelopeCut = null) |
|
{ |
|
List<TileInfo> tiles = new List<TileInfo>(); |
|
double originX = extent.XMin; |
|
double originY = extent.YMax; |
|
for (int level = 0; level < Level; level++) |
|
{ |
|
int count = (int)Math.Pow(2, level); |
|
double del = extent.Width / count; |
|
for (int col = 0; col < count; col++) |
|
{ |
|
for (int row = 0; row < count; row++) |
|
{ |
|
double minx = originX + col * del; |
|
double maxy = originY - row * del; |
|
|
|
Envelope e = new Envelope() |
|
{ |
|
XMin = minx, |
|
YMin = maxy - del, |
|
XMax = minx + del, |
|
YMax = maxy |
|
}; |
|
if (envelopeCut != null) |
|
{ |
|
if (!e.Intersects(envelopeCut)) continue; |
|
} |
|
tiles.Add(new TileInfo(e, level, row, col)); |
|
} |
|
} |
|
} |
|
return tiles; |
|
} |
|
|
|
|
|
public static Rectangle Envelope2Rect(RasterInfo rasterInfo, Envelope extent) |
|
{ |
|
//int width = (int)((extent.XMax - extent.XMin) / rasterInfo.TransScale + 0.5); |
|
//int height = (int)((extent.YMax - extent.YMin) / rasterInfo.TransScale + 0.5); |
|
//int x = (int)((rasterInfo.Extent.XMax - extent.XMax) / rasterInfo.TransScale + 0.5); |
|
//int y = (int)((rasterInfo.Extent.YMax - extent.YMax) / rasterInfo.TransScale + 0.5); |
|
//return new Rectangle(x, y, width, height); |
|
Rectangle rect = Envelope2Rect(rasterInfo.Extent, extent, rasterInfo.TransScale); |
|
if (rect.Right > rasterInfo.XSize) |
|
{ |
|
rect.Width -= rect.Right - rasterInfo.XSize; |
|
} |
|
if (rect.Bottom > rasterInfo.YSize) |
|
{ |
|
rect.Height -= rect.Bottom - rasterInfo.YSize; |
|
} |
|
return rect; |
|
} |
|
|
|
public static Rectangle Envelope2Rect(Envelope baseExtent, Envelope extent, double resolution) |
|
{ |
|
int width = (int)((extent.XMax - extent.XMin) / resolution + 0.5); |
|
int height = (int)((extent.YMax - extent.YMin) / resolution + 0.5); |
|
int x = (int)((extent.XMin - baseExtent.XMin) / resolution + 0.5); |
|
int y = (int)((baseExtent.YMax - extent.YMax) / resolution + 0.5); |
|
return new Rectangle(x, y, width, height); |
|
} |
|
|
|
private Envelope GetExtent() |
|
{ |
|
return GetExtent(this.Rasters); |
|
} |
|
|
|
private static Envelope GetExtent(List<RasterInfo> rasters) |
|
{ |
|
Envelope extent = rasters[0].Extent; ; |
|
for (int i = 1; i < rasters.Count; i++) |
|
{ |
|
extent = extent.Union(rasters[i].Extent); |
|
} |
|
return extent; |
|
} |
|
|
|
|
|
private static Envelope GetExtentZ(Envelope e) |
|
{ |
|
Envelope extent = new Envelope() |
|
{ |
|
XMax = e.XMax, |
|
XMin = e.XMin, |
|
YMax = e.YMax, |
|
YMin = e.YMin |
|
}; |
|
double del = (extent.Width - extent.Height) / 2; |
|
if (del > 0) |
|
{ |
|
extent.YMax += del; |
|
extent.YMin -= del; |
|
} |
|
else |
|
{ |
|
extent.XMax -= del; |
|
extent.XMin += del; |
|
} |
|
return extent; |
|
} |
|
|
|
private Envelope maxExtent = null; |
|
|
|
|
|
private string EnCode(object value) |
|
{ |
|
|
|
if (value == null) |
|
return ""; |
|
string str = value.ToString(); |
|
return str; |
|
if (string.IsNullOrEmpty(str)) |
|
return ""; |
|
string outStr = ""; |
|
foreach (char item in str) |
|
{ |
|
outStr += (char)(item + 22); |
|
} |
|
return outStr; |
|
} |
|
|
|
//多线程去切 |
|
private List<ReadRaster> readRasterList = new List<ReadRaster>(); |
|
private WriteDatabase pWriteDatabase = null; |
|
public void CreateMulFilesKOTiles(List<string> files, int threadnumber, bool converWebMercator, SpatialReference spatialReference, Envelope envelopeCut = null) |
|
{ |
|
foreach (var fileName in files) |
|
{ |
|
try |
|
{ |
|
RasterInfo raster = RasterInfo.Create(fileName); |
|
if (converWebMercator == true) |
|
{ |
|
if (spatialReference != null) |
|
{ |
|
Dataset mercatorDataSet = GdalWarp(fileName, spatialReference); |
|
if (mercatorDataSet != null) |
|
raster = RasterInfo.Create(mercatorDataSet); |
|
} |
|
} |
|
|
|
if (raster != null) |
|
Rasters.Add(raster); |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("获取影像信息失败:" + ex.Message); |
|
}; |
|
} |
|
//创建遮罩层 |
|
if (TopLayer != null) |
|
CreateLayer(); |
|
|
|
//计算全部图层的最小外接正方形 |
|
this.rasterExtent = GetExtent(); |
|
maxExtent = GetExtentZ(rasterExtent); |
|
//开始切片,获取范围内的瓦片 |
|
//根据层级开始计算网格个数 |
|
List<TileInfo> allTiles = GetAllTiles(maxExtent, envelopeCut); |
|
|
|
List<List<TileInfo>> tileGroups = new List<List<TileInfo>>(); |
|
int start = 0; |
|
int count = allTiles.Count / threadnumber; |
|
if (topRasterDs != null) |
|
topRaster = RasterInfo.Create(topRasterDs); |
|
|
|
pWriteDatabase = new WriteDatabase(); |
|
|
|
for (int i = 0; i < threadnumber; i++) |
|
{ |
|
if (i == threadnumber - 1) |
|
{ |
|
count += allTiles.Count % threadnumber; |
|
} |
|
List<TileInfo> tileGroup = allTiles.GetRange(start, count); |
|
|
|
start += count; |
|
|
|
ReadRaster pReadRaster = new ReadRaster() |
|
{ |
|
ImgFormat = ImgFormat, |
|
TiledSize = TiledSize, |
|
TileInfos = tileGroup, |
|
TopRasterInfo = topRaster, |
|
CompressRate = this.CompressRate, |
|
Rasters = Rasters |
|
}; |
|
|
|
|
|
pReadRaster.Dowork(); |
|
|
|
pReadRaster.Event2 += (d, e) => { |
|
pWriteDatabase.InsertDataRange(d as TileInfo[]); |
|
}; |
|
|
|
readRasterList.Add(pReadRaster); |
|
} |
|
|
|
SQLiteConnection conn = null; |
|
if (SaveType == EnumSaveType.Level) |
|
conn = CreateDataBase(); |
|
else if (SaveType == EnumSaveType.Resolution) |
|
conn = CreateBestDataBase(); |
|
|
|
pWriteDatabase.Conn = conn; |
|
pWriteDatabase.TileCount = allTiles.Count; |
|
pWriteDatabase.Done += (s, e) => |
|
{ |
|
if (topRaster != null) |
|
topRaster.Dispose(); |
|
if (topRasterDs != null) |
|
{ |
|
topRasterDs.Dispose(); |
|
topRasterDs = null; |
|
} |
|
if (TopLayer != null) |
|
{ |
|
TopLayer.Dispose(); |
|
TopLayer = null; |
|
} |
|
this.CreatDown(s, e); |
|
|
|
}; |
|
pWriteDatabase.Report += (s, e) => |
|
{ |
|
if (Report != null) |
|
{ |
|
Report(s, e); |
|
} |
|
}; |
|
if (SaveType == EnumSaveType.Level) |
|
{ |
|
pWriteDatabase.DoWorkLevel(); |
|
} |
|
else if (SaveType == EnumSaveType.Resolution) |
|
{ |
|
pWriteDatabase.BestDoWork(); |
|
} |
|
} |
|
|
|
public void CreateMulFilesKOTiles(List<string> files, int threadnumber, bool converWebMercator, Envelope envelopeCut = null) |
|
{ |
|
foreach (string file in files) |
|
{ |
|
try |
|
{ |
|
RasterInfo rasterInfo = RasterInfo.Create(file); |
|
if (converWebMercator) |
|
{ |
|
SpatialReference spatialReference = new SpatialReference(""); |
|
spatialReference.ImportFromEPSG(3857); |
|
Dataset dataset = GdalWarp(file, spatialReference); |
|
if (dataset != null) |
|
{ |
|
rasterInfo = RasterInfo.Create(dataset); |
|
} |
|
} |
|
if (rasterInfo != null) |
|
{ |
|
Rasters.Add(rasterInfo); |
|
} |
|
} |
|
catch |
|
{ |
|
} |
|
} |
|
if (TopLayer != null) |
|
{ |
|
CreateLayer(); |
|
} |
|
rasterExtent = GetExtent(); |
|
maxExtent = GetExtentZ(rasterExtent); |
|
List<TileInfo> allTiles = GetAllTiles(maxExtent, envelopeCut); |
|
List<List<TileInfo>> list = new List<List<TileInfo>>(); |
|
int num = 0; |
|
int num2 = allTiles.Count / threadnumber; |
|
if (topRasterDs != null) |
|
{ |
|
topRaster = RasterInfo.Create(topRasterDs); |
|
} |
|
pWriteDatabase = new WriteDatabase(); |
|
for (int i = 0; i < threadnumber; i++) |
|
{ |
|
if (i == threadnumber - 1) |
|
{ |
|
num2 += allTiles.Count % threadnumber; |
|
} |
|
List<TileInfo> range = allTiles.GetRange(num, num2); |
|
num += num2; |
|
ReadRaster readRaster = new ReadRaster(files, converWebMercator) |
|
{ |
|
ImgFormat = ImgFormat, |
|
TiledSize = TiledSize, |
|
TileInfos = range, |
|
TopRasterInfo = topRaster, |
|
CompressRate = CompressRate |
|
}; |
|
readRaster.Dowork(); |
|
readRaster.Event2 += delegate (object d, EventArgs e) |
|
{ |
|
pWriteDatabase.InsertDataRange(d as TileInfo[]); |
|
}; |
|
readRasterList.Add(readRaster); |
|
} |
|
SQLiteConnection conn = null; |
|
if (SaveType == EnumSaveType.Level) |
|
{ |
|
conn = CreateDataBase(); |
|
} |
|
else if (SaveType == EnumSaveType.Resolution) |
|
{ |
|
conn = CreateBestDataBase(); |
|
} |
|
pWriteDatabase.Conn = conn; |
|
pWriteDatabase.TileCount = allTiles.Count; |
|
pWriteDatabase.Done += delegate (object s, EventArgs e) |
|
{ |
|
if (topRaster != null) |
|
{ |
|
topRaster.Dispose(); |
|
} |
|
if (topRasterDs != null) |
|
{ |
|
topRasterDs.Dispose(); |
|
topRasterDs = null; |
|
} |
|
if (TopLayer != null) |
|
{ |
|
TopLayer.Dispose(); |
|
TopLayer = null; |
|
} |
|
this.CreatDown(s, e); |
|
}; |
|
pWriteDatabase.Report += delegate (int s, int e) |
|
{ |
|
if (this.Report != null) |
|
{ |
|
this.Report(s, e); |
|
} |
|
}; |
|
if (SaveType == EnumSaveType.Level) |
|
{ |
|
pWriteDatabase.DoWorkLevel(); |
|
} |
|
else if (SaveType == EnumSaveType.Resolution) |
|
{ |
|
pWriteDatabase.BestDoWork(); |
|
} |
|
} |
|
|
|
|
|
public static Dataset GdalWarp(string inputFile, SpatialReference tileSpatialReference) |
|
{ |
|
Dataset inputDataset = Gdal.OpenShared(inputFile, Access.GA_ReadOnly); |
|
OSGeo.OSR.SpatialReference sSpatialReference = inputDataset.GetSpatialRef(); |
|
if (sSpatialReference.IsSame(tileSpatialReference, null) > 0) |
|
{ |
|
return inputDataset; |
|
} |
|
try |
|
{ |
|
string tempFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Temp"); |
|
if (!Directory.Exists(tempFolder)) |
|
{ |
|
Directory.CreateDirectory(tempFolder); |
|
} |
|
string outputFile = System.IO.Path.Combine(tempFolder, Guid.NewGuid().ToString().Replace("-", "") + ".VRT"); |
|
tileSpatialReference.ExportToWkt(out string wkt, null); |
|
string[] options = new string[] { "-t_srs", wkt, "-r", "rms", "-of", "VRT" }; |
|
|
|
Gdal.GDALProgressFuncDelegate progressFuncDelegate = new Gdal.GDALProgressFuncDelegate((complete, msg, data) => |
|
{ |
|
if (complete >= 1) |
|
{ |
|
//isProgressCompleted = true; |
|
} |
|
return 1; |
|
}); |
|
return Gdal.Warp(outputFile, new Dataset[] { inputDataset }, new GDALWarpAppOptions(options), progressFuncDelegate, null); |
|
} |
|
finally |
|
{ |
|
inputDataset.Dispose(); |
|
} |
|
} |
|
|
|
private SQLiteConnection CreateDataBase() |
|
{ |
|
string connString = "Data Source=" + this.MBTilesPath; |
|
if (File.Exists(this.MBTilesPath)) |
|
{ |
|
GC.Collect(); |
|
System.Windows.Forms.Application.DoEvents(); |
|
try |
|
{ |
|
File.Delete(this.MBTilesPath); |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("输出文件监测到被占用,请重试!" + ex.Message); |
|
} |
|
} |
|
string dir = Path.GetDirectoryName(this.MBTilesPath); |
|
if (!Directory.Exists(dir)) |
|
{ |
|
Directory.CreateDirectory(dir); |
|
} |
|
try |
|
{ |
|
File.WriteAllBytes(this.MBTilesPath, Properties.Resources.Template); |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("创建数据库失败:" + ex.Message); |
|
} |
|
System.Data.SQLite.SQLiteConnection conn = new System.Data.SQLite.SQLiteConnection(connString); |
|
conn.Open(); |
|
try |
|
{ |
|
SQLiteTransaction pTan = conn.BeginTransaction(); |
|
SQLiteCommand cmd = new SQLiteCommand(conn); |
|
string sqlFormat = "insert into metadata values('{0}','{1}')"; |
|
//写入图片大小 |
|
cmd.CommandText = string.Format(sqlFormat, "Size", EnCode(this.TiledSize)); |
|
int result= cmd.ExecuteNonQuery(); |
|
//写入图片格式 |
|
cmd.CommandText = string.Format(sqlFormat, "Format", EnCode(ImgFormat.ToString())); |
|
result=cmd.ExecuteNonQuery(); |
|
//写入空间参考 |
|
cmd.CommandText = string.Format(sqlFormat, "Projection", EnCode(this.Rasters[0].Dataset.GetProjection())); |
|
result = cmd.ExecuteNonQuery(); |
|
//写入Extend |
|
cmd.CommandText = string.Format(sqlFormat, "Bounds", |
|
EnCode(string.Format("{0},{1},{2},{3}", this.rasterExtent.XMin, rasterExtent.YMin, rasterExtent.XMax, rasterExtent.YMax))); |
|
result = cmd.ExecuteNonQuery(); |
|
//写入origin |
|
cmd.CommandText = string.Format(sqlFormat, "Origin", |
|
EnCode(string.Format("{0},{1}", maxExtent.XMin, maxExtent.YMax))); |
|
result = cmd.ExecuteNonQuery(); |
|
//写入分辨率 |
|
double dbResolution = maxExtent.Width / this.TiledSize; |
|
cmd.CommandText = string.Format(sqlFormat, "Resolution", EnCode(dbResolution)); |
|
result = cmd.ExecuteNonQuery(); |
|
//写入比例尺 |
|
double dbScale = (96 / 0.0254) * dbResolution; |
|
cmd.CommandText = string.Format(sqlFormat, "Scale", EnCode(dbScale)); |
|
result = cmd.ExecuteNonQuery(); |
|
//写入Level |
|
cmd.CommandText = string.Format(sqlFormat, "Level", EnCode(this.Level)); |
|
result = cmd.ExecuteNonQuery(); |
|
|
|
|
|
//写入Kingo |
|
cmd.CommandText = string.Format(sqlFormat, "Kingo", "false"); |
|
cmd.ExecuteNonQuery(); |
|
cmd.Dispose(); |
|
pTan.Commit(); |
|
pTan.Dispose(); |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("写入metadata表数据失败:" + ex.Message); |
|
} |
|
finally |
|
{ |
|
conn.Close(); |
|
GC.Collect(); |
|
} |
|
return conn; |
|
} |
|
|
|
public event EventHandler CreatDown; |
|
public event ProgressReport Report; |
|
|
|
|
|
private void CreateLayer() |
|
{ |
|
// 注册所有的驱动 |
|
// Ogr.RegisterAll(); |
|
//Gdal.AllRegister(); |
|
//消除中文路径无法识别的问题 |
|
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); |
|
//解决shape文件字段中文内容读取问题 |
|
OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8"); |
|
|
|
//获取transform |
|
Envelope maxEnvelope = GetExtent(this.Rasters); |
|
|
|
int[] rasterSize = GetRasterSize(maxEnvelope); |
|
double[] geoTransform = GetGeoTransform(maxEnvelope, rasterSize[0], rasterSize[1]); |
|
|
|
Layer layer = TopLayer; |
|
|
|
topRasterDs = null; |
|
string tempFile = Application.StartupPath + "\\temp.img"; |
|
if (File.Exists(tempFile)) |
|
File.Delete(tempFile); |
|
OSGeo.GDAL.Driver dirver = Gdal.GetDriverByName("HFA");//MEM HFA GTiff |
|
topRasterDs = dirver.Create(tempFile, rasterSize[0], rasterSize[1], 1, DataType.GDT_Byte, null); |
|
topRasterDs.SetProjection(this.Rasters[0].Projection); |
|
topRasterDs.SetGeoTransform(geoTransform); |
|
|
|
Gdal.GDALProgressFuncDelegate callback = new Gdal.GDALProgressFuncDelegate(GDALProgressFuncDelegate); |
|
try |
|
{ |
|
int rst = Gdal.RasterizeLayer(topRasterDs, 1, new int[] { 1 }, layer, IntPtr.Zero, IntPtr.Zero, 1, new double[] { 255 }, new string[] { "ALL_TOUCHED=TRUE" }, callback, "callback"); |
|
} |
|
catch (Exception ex) |
|
{ |
|
} |
|
|
|
} |
|
|
|
private double[] GetGeoTransform(Envelope envelope, int x, int y) |
|
{ |
|
double[] geoTransform = new double[6]; |
|
|
|
geoTransform[0] = envelope.XMin; |
|
geoTransform[1] = envelope.Width / x; |
|
geoTransform[2] = 0; |
|
geoTransform[3] = envelope.YMax; |
|
geoTransform[4] = 0; |
|
geoTransform[5] = -envelope.Height / y; |
|
|
|
return geoTransform; |
|
} |
|
|
|
private int[] GetRasterSize(Envelope envelope) |
|
{ |
|
|
|
int[] rasterSize = new int[2]; |
|
rasterSize[0] = (int)(envelope.Width / 10); |
|
rasterSize[1] = (int)(envelope.Height / 10); |
|
return rasterSize; |
|
} |
|
|
|
|
|
bool isComplete = false; |
|
private int GDALProgressFuncDelegate(double Complete, IntPtr Message, IntPtr Data) |
|
{ |
|
if (Complete >= 1) |
|
{ |
|
isComplete = true; |
|
} |
|
return 1; |
|
} |
|
|
|
#region 裁取图斑最高分辨率 2015-11-11 chendewen |
|
|
|
|
|
private SQLiteConnection CreateBestDataBase() |
|
{ |
|
string connString = "Data Source=" + this.MBTilesPath; |
|
if (File.Exists(this.MBTilesPath)) |
|
{ |
|
GC.Collect(); |
|
System.Windows.Forms.Application.DoEvents(); |
|
try |
|
{ |
|
File.Delete(this.MBTilesPath); |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw new Exception("输出文件监测到被占用,请重试!"); |
|
} |
|
} |
|
string dir = Path.GetDirectoryName(this.MBTilesPath); |
|
if (!Directory.Exists(dir)) |
|
{ |
|
Directory.CreateDirectory(dir); |
|
} |
|
File.WriteAllBytes(this.MBTilesPath, Properties.Resources.model); |
|
System.Data.SQLite.SQLiteConnection conn = new System.Data.SQLite.SQLiteConnection(connString); |
|
return conn; |
|
} |
|
#endregion |
|
} |
|
|
|
public class TileInfo |
|
{ |
|
public Envelope Bound { get; private set; } |
|
public int Level { get; private set; } |
|
public int Row { get; private set; } |
|
public int Column { get; private set; } |
|
public byte[] Data { get; set; } |
|
public double Resolution { get; set; } |
|
|
|
public TileInfo(Envelope bound, int level, int row, int col) |
|
{ |
|
this.Bound = bound; |
|
this.Level = level; |
|
this.Row = row; |
|
this.Column = col; |
|
} |
|
} |
|
|
|
|
|
internal class ReadRaster : IDisposable |
|
{ |
|
public ImageFormat ImgFormat { get; set; } |
|
public int TiledSize { get; set; } |
|
|
|
public List<RasterInfo> Rasters { get; set; } |
|
public List<TileInfo> TileInfos { get; set; } |
|
public int CompressRate { get; set; } = 25; |
|
|
|
public ReadRaster() |
|
{ |
|
} |
|
|
|
public RasterInfo TopRasterInfo { get; set; } |
|
public ReadRaster(List<string> files, bool converWebMercator) |
|
{ |
|
Rasters = new List<RasterInfo>(); |
|
foreach (var fileName in files) |
|
{ |
|
try |
|
{ |
|
RasterInfo raster = RasterInfo.Create(fileName); |
|
|
|
if (converWebMercator == true) |
|
{ |
|
SpatialReference spatialReference = new SpatialReference(""); |
|
spatialReference.ImportFromEPSG(3857); |
|
|
|
Dataset mercatorDataSet = GdalWarp(fileName, spatialReference); |
|
if (mercatorDataSet != null) |
|
raster = RasterInfo.Create(mercatorDataSet); |
|
|
|
} |
|
|
|
if (raster != null) |
|
Rasters.Add(raster); |
|
} |
|
catch { }; |
|
} |
|
|
|
} |
|
|
|
private static Dataset GdalWarp(string inputFile, SpatialReference tileSpatialReference) |
|
{ |
|
Dataset inputDataset = Gdal.OpenShared(inputFile, Access.GA_ReadOnly); |
|
OSGeo.OSR.SpatialReference sSpatialReference = inputDataset.GetSpatialRef(); |
|
if (sSpatialReference.IsSame(tileSpatialReference, null) > 0) |
|
{ |
|
return inputDataset; |
|
} |
|
|
|
try |
|
{ |
|
string tempFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Temp"); |
|
if (!Directory.Exists(tempFolder)) |
|
{ |
|
Directory.CreateDirectory(tempFolder); |
|
} |
|
string outputFile = System.IO.Path.Combine(tempFolder, Guid.NewGuid().ToString().Replace("-", "") + ".VRT"); |
|
tileSpatialReference.ExportToWkt(out string wkt, null); |
|
string[] options = new string[] { "-t_srs", wkt, "-r", "rms", "-of", "VRT" }; |
|
Gdal.GDALProgressFuncDelegate progressFuncDelegate = new Gdal.GDALProgressFuncDelegate((complete, msg, data) => |
|
{ |
|
if (complete >= 1) |
|
{ |
|
//isProgressCompleted = true; |
|
} |
|
return 1; |
|
}); |
|
return Gdal.Warp(outputFile, new Dataset[] { inputDataset }, new GDALWarpAppOptions(options), progressFuncDelegate, null); |
|
} |
|
finally |
|
{ |
|
inputDataset.Dispose(); |
|
} |
|
} |
|
|
|
//创建单个瓦片 |
|
private void CreateKOTiles(TileInfo tile) |
|
{ |
|
|
|
try |
|
{ |
|
byte[] bgra = new byte[TiledSize * TiledSize * 4]; |
|
double resolution = tile.Bound.Width / this.TiledSize; |
|
|
|
bool isExist = false; |
|
byte[] rgbTop = null; |
|
Rectangle dTopRect = new Rectangle(); |
|
if (TopRasterInfo != null) |
|
{ |
|
Envelope topEnvelope = tile.Bound.Intersection(TopRasterInfo.Extent); |
|
if (topEnvelope != null) |
|
{ |
|
try |
|
{ |
|
Rectangle sTopRect = MultRaster2MBTiles.Envelope2Rect(TopRasterInfo, topEnvelope); |
|
dTopRect = MultRaster2MBTiles.Envelope2Rect(tile.Bound, topEnvelope, resolution); |
|
rgbTop = new byte[dTopRect.Width * dTopRect.Height]; |
|
CPLErr err = TopRasterInfo.Dataset.GetRasterBand(1).ReadRaster(sTopRect.X, sTopRect.Y, sTopRect.Width, sTopRect.Height, rgbTop, dTopRect.Width, dTopRect.Height, 0, 0); |
|
if (err != CPLErr.CE_None) |
|
{ |
|
Console.WriteLine(string.Format("读取Level:{0},Column:{1},Row:{2}的瓦片出错!", tile.Level, tile.Column, tile.Row)); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
//Console.WriteLine(string.Format("读取Level:{0},Column:{1},Row:{2}的瓦片出错!", tile.Level, tile.Column, tile.Row)); |
|
} |
|
|
|
//填充数据到bgra |
|
for (int i = 0; i < dTopRect.Width; i++) |
|
{ |
|
for (int j = 0; j < dTopRect.Height; j++) |
|
{ |
|
try |
|
{ |
|
int offset = i + j * dTopRect.Width; |
|
byte rVal = rgbTop[offset]; |
|
if (rVal > 250) |
|
{ |
|
isExist = true; |
|
break; |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("填充数据到bgra失败:" + ex.Message); |
|
} |
|
} |
|
} |
|
} |
|
//没有数据 |
|
if (!isExist) |
|
return; |
|
} |
|
|
|
foreach (var raster in Rasters) |
|
{ |
|
Envelope pEnvelope = tile.Bound.Intersection(raster.Extent); |
|
if (pEnvelope == null) |
|
continue; |
|
Rectangle sRect = MultRaster2MBTiles.Envelope2Rect(raster, pEnvelope); |
|
Rectangle dRect = MultRaster2MBTiles.Envelope2Rect(tile.Bound, pEnvelope, resolution); |
|
if (raster.Bands > 2) |
|
{ |
|
byte[] rgb = new byte[dRect.Width * dRect.Height * 3]; |
|
try |
|
{ |
|
CPLErr err = raster.Dataset.ReadRaster(sRect.X, sRect.Y, sRect.Width, sRect.Height, rgb, dRect.Width, dRect.Height, 3, new int[] { 1, 2, 3 }, 0, 0, 0); |
|
if (err != CPLErr.CE_None) |
|
{ |
|
Console.WriteLine(string.Format("读取Level:{0},Column:{1},Row:{2}的瓦片出错!", tile.Level, tile.Column, tile.Row)); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
} |
|
//填充数据到bgra |
|
for (int i = 0; i < dRect.Width; i++) |
|
{ |
|
for (int j = 0; j < dRect.Height; j++) |
|
{ |
|
try |
|
{ |
|
int offset = i + j * dRect.Width; |
|
byte rVal = rgb[offset]; |
|
byte gVal = rgb[offset + dRect.Width * dRect.Height]; |
|
byte bVal = rgb[offset + dRect.Width * dRect.Height * 2]; |
|
|
|
if ((rVal == 0 && gVal == 0 && bVal == 0) || (rVal == 255 && gVal == 255 && bVal == 255)) |
|
{ |
|
continue; |
|
} |
|
int pixelPos = (dRect.X + i) + (dRect.Y + j) * this.TiledSize; |
|
bgra[pixelPos * 4] = bVal; |
|
bgra[pixelPos * 4 + 1] = gVal; |
|
bgra[pixelPos * 4 + 2] = rVal; |
|
bgra[pixelPos * 4 + 3] = 255; |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("填充数据到bgra失败:" +ex.Message); |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
byte[] r = new byte[dRect.Width * dRect.Height]; |
|
|
|
try |
|
{ |
|
CPLErr err = raster.Dataset.GetRasterBand(1).ReadRaster(sRect.X, sRect.Y, sRect.Width, sRect.Height, r, dRect.Width, dRect.Height, 0, 0); |
|
if (err != CPLErr.CE_None) |
|
{ |
|
Console.WriteLine(string.Format("读取Level:{0},Column:{1},Row:{2}的瓦片出错!", tile.Level, tile.Column, tile.Row)); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
} |
|
|
|
//填充数据到bgra |
|
for (int i = 0; i < dRect.Width; i++) |
|
{ |
|
for (int j = 0; j < dRect.Height; j++) |
|
{ |
|
try |
|
{ |
|
int offset = i + j * dRect.Width; |
|
byte rVal = r[offset]; |
|
if (rVal < 5) |
|
continue; |
|
int pixelPos = (dRect.X + i) + (dRect.Y + j) * this.TiledSize; |
|
bgra[pixelPos * 4] = rVal; |
|
bgra[pixelPos * 4 + 1] = rVal; |
|
bgra[pixelPos * 4 + 2] = rVal; |
|
bgra[pixelPos * 4 + 3] = 255; |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("填充数据到bgra失败:" + ex.Message); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
if (rgbTop != null) |
|
{ |
|
//填充数据到bgra |
|
for (int i = 0; i < dTopRect.Width; i++) |
|
{ |
|
for (int j = 0; j < dTopRect.Height; j++) |
|
{ |
|
try |
|
{ |
|
int offset = i + j * dTopRect.Width; |
|
byte rVal = rgbTop[offset]; |
|
if (rVal > 250) |
|
{ |
|
continue; |
|
} |
|
int pixelPos = (dTopRect.X + i) + (dTopRect.Y + j) * this.TiledSize; |
|
bgra[pixelPos * 4] = 255; |
|
bgra[pixelPos * 4 + 1] = 255; |
|
bgra[pixelPos * 4 + 2] = 255; |
|
bgra[pixelPos * 4 + 3] = 0; |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("填充数据到bgra失败:" + ex.Message); |
|
} |
|
} |
|
} |
|
} |
|
|
|
int dataHasValue = 0; |
|
for (int i = 0; i < TiledSize * TiledSize; i++) |
|
{ |
|
if (bgra[i * 4 + 3] != 0) |
|
{ |
|
dataHasValue++; |
|
} |
|
} |
|
//没有数据 |
|
if (dataHasValue < 1) |
|
return; |
|
|
|
|
|
//写入数据文件 |
|
using (MemoryStream ms = new MemoryStream()) |
|
{ |
|
Bitmap bitmap = new Bitmap(TiledSize, TiledSize, System.Drawing.Imaging.PixelFormat.Format32bppArgb); |
|
try |
|
{ |
|
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); |
|
try |
|
{ |
|
Marshal.Copy(bgra, 0, bitmapData.Scan0, bgra.Length); |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("拷贝bgra失败:" + ex.Message); |
|
} |
|
finally |
|
{ |
|
bitmap.UnlockBits(bitmapData); |
|
} |
|
if (ImageFormat.Jpeg.Equals(ImgFormat) || dataHasValue > this.TiledSize * (this.TiledSize - 1)) |
|
{ |
|
EncoderParameter p; |
|
EncoderParameters ps; |
|
|
|
ps = new EncoderParameters(1); |
|
|
|
p = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)this.CompressRate); |
|
ps.Param[0] = p; |
|
ImageCodecInfo pngEncoder = GetEncoder(ImageFormat.Jpeg); |
|
bitmap.Save(ms, pngEncoder, ps); |
|
|
|
} |
|
else |
|
{ |
|
string path = AppDomain.CurrentDomain.BaseDirectory + @"pngquant\pngquant.exe"; |
|
if (File.Exists(path)) |
|
{ |
|
PngQuant.Run(bitmap, ms, path); |
|
} |
|
else |
|
{ |
|
bitmap.Save(ms, ImageFormat.Png); |
|
} |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("写入数据文件失败:" + ex.Message); |
|
} |
|
finally |
|
{ |
|
bitmap.Dispose(); |
|
} |
|
tile.Data = ms.ToArray(); |
|
tile.Resolution = resolution; |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("创建单个瓦片失败:" + ex.Message); |
|
} |
|
} |
|
|
|
bool isY = false; |
|
private ImageCodecInfo GetEncoder(ImageFormat format) |
|
{ |
|
|
|
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); |
|
|
|
foreach (ImageCodecInfo codec in codecs) |
|
{ |
|
if (codec.FormatID == format.Guid) |
|
{ |
|
return codec; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
private Thread doThread; |
|
public event EventHandler Event2; |
|
public void Dowork() |
|
{ |
|
doThread = new Thread(new ThreadStart(read)); |
|
doThread.IsBackground = true; |
|
doThread.Name = "读取图片线程" + Guid.NewGuid().ToString(); |
|
doThread.Priority = ThreadPriority.Highest; |
|
doThread.Start(); |
|
} |
|
|
|
|
|
private List<TileInfo> doneList = new List<TileInfo>(); |
|
public void read() |
|
{ |
|
foreach (var item in TileInfos) |
|
{ |
|
try |
|
{ |
|
CreateKOTiles(item); |
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("读取图片线程异常" + ex.Message); |
|
} |
|
finally |
|
{ |
|
doneList.Add(item); |
|
if (doneList.Count > 20) |
|
{ |
|
Event2?.Invoke(doneList.ToArray(), null); |
|
doneList.Clear(); |
|
} |
|
} |
|
} |
|
if (doneList.Count > 0) |
|
{ |
|
Event2?.Invoke(doneList.ToArray(), null); |
|
doneList.Clear(); |
|
} |
|
Console.WriteLine(doThread.Name + "结束"); |
|
} |
|
|
|
public void Stop() |
|
{ |
|
this.Dispose(); |
|
} |
|
|
|
public void Dispose() |
|
{ |
|
if (this.doThread != null) |
|
{ |
|
try |
|
{ |
|
this.doThread.Abort(); |
|
} |
|
catch { } |
|
finally |
|
{ |
|
this.doThread = null; |
|
} |
|
} |
|
} |
|
|
|
|
|
} |
|
public delegate void ProgressReport(int sum, int current); |
|
internal class WriteDatabase : IDisposable |
|
{ |
|
public event ProgressReport Report; |
|
public SQLiteConnection Conn { get; set; } |
|
public int TileCount { get; set; } |
|
private List<TileInfo> needInsertDataList = new List<TileInfo>(); |
|
|
|
|
|
public void InsertDataRange(TileInfo[] data) |
|
{ |
|
lock (needInsertDataList) |
|
{ |
|
needInsertDataList.AddRange(data); |
|
} |
|
} |
|
|
|
Thread doworkThread = null; |
|
|
|
public event EventHandler Done; |
|
|
|
|
|
public void Dispose() |
|
{ |
|
if (doworkThread != null) |
|
{ |
|
try |
|
{ |
|
doworkThread.Abort(); |
|
} |
|
catch |
|
{ |
|
|
|
} |
|
finally |
|
{ |
|
doworkThread = null; |
|
} |
|
} |
|
} |
|
|
|
public void BestDoWork() |
|
{ |
|
doworkThread = new Thread(new ThreadStart(WriteTodb)); |
|
doworkThread.IsBackground = true; |
|
doworkThread.Name = "写入图片线程" + Guid.NewGuid().ToString(); |
|
doworkThread.Start(); |
|
} |
|
|
|
private void WriteTodb() |
|
{ |
|
Conn.Open(); |
|
try |
|
{ |
|
SQLiteTransaction pTan = Conn.BeginTransaction(); |
|
SQLiteCommand cmd = new SQLiteCommand(Conn); |
|
cmd.CommandText = "insert into tiles (centerX,centerY,maxX,maxY,minX,minY,resolution,tile_Data) values(@centerX,@centerY,@maxX,@maxY,@minX,@minY,@resolution,@tile_Data)"; |
|
cmd.Parameters.Add(new SQLiteParameter("@centerX", System.Data.DbType.Double)); |
|
cmd.Parameters.Add(new SQLiteParameter("@centerY", System.Data.DbType.Double)); |
|
cmd.Parameters.Add(new SQLiteParameter("@maxX", System.Data.DbType.Double)); |
|
cmd.Parameters.Add(new SQLiteParameter("@maxY", System.Data.DbType.Double)); |
|
cmd.Parameters.Add(new SQLiteParameter("@minX", System.Data.DbType.Double)); |
|
cmd.Parameters.Add(new SQLiteParameter("@minY", System.Data.DbType.Double)); |
|
cmd.Parameters.Add(new SQLiteParameter("@resolution", System.Data.DbType.Double)); |
|
cmd.Parameters.Add(new SQLiteParameter("@tile_Data", System.Data.DbType.Binary)); |
|
int dealTileCount = 0; |
|
while (dealTileCount < TileCount) |
|
{ |
|
TileInfo[] datas = null; |
|
lock (needInsertDataList) |
|
{ |
|
datas = needInsertDataList.ToArray(); |
|
needInsertDataList.Clear(); |
|
} |
|
if (datas == null || datas.Length == 0) |
|
{ |
|
Thread.Sleep(1000); |
|
} |
|
else |
|
{ |
|
foreach (var item in datas) |
|
{ |
|
if (item.Data == null) |
|
continue; |
|
cmd.Parameters[0].Value = (item.Bound.XMax - item.Bound.XMin) / 2 + item.Bound.XMin; |
|
cmd.Parameters[1].Value = (item.Bound.YMax - item.Bound.YMin) / 2 + item.Bound.YMin; |
|
cmd.Parameters[2].Value = item.Bound.XMax; |
|
cmd.Parameters[3].Value = item.Bound.YMax; |
|
cmd.Parameters[4].Value = item.Bound.XMin; |
|
cmd.Parameters[5].Value = item.Bound.YMin; |
|
cmd.Parameters[6].Value = item.Resolution; |
|
cmd.Parameters[7].Value = item.Data; |
|
cmd.ExecuteNonQuery(); |
|
item.Data = null; |
|
} |
|
dealTileCount += datas.Length; |
|
if (Report != null) |
|
{ |
|
Report(TileCount, dealTileCount); |
|
} |
|
} |
|
Thread.Sleep(0); |
|
} |
|
cmd.CommandText = "CREATE INDEX tiles_index ON tiles (centerX,centerY,maxX,maxY,minX,minY);"; |
|
cmd.ExecuteNonQuery(); |
|
pTan.Commit(); |
|
pTan.Dispose(); |
|
if (Done != null) |
|
{ |
|
Done(null, null); |
|
} |
|
} |
|
finally |
|
{ |
|
Conn.Close(); |
|
Conn.Dispose(); |
|
SQLiteConnection.ClearPool(Conn); |
|
Thread.Sleep(10); |
|
GC.Collect(); |
|
Thread.Sleep(10); |
|
} |
|
} |
|
|
|
Thread doworkThreadLevel = null; |
|
public void DoWorkLevel() |
|
{ |
|
//doworkThreadLevel = new Thread(new ThreadStart(WriteTodbLevel)); |
|
//doworkThreadLevel.IsBackground = true; |
|
//doworkThreadLevel.Name = "写入图片线程" + Guid.NewGuid().ToString(); |
|
//doworkThreadLevel.Start(); |
|
WriteTodbLevel(); |
|
} |
|
|
|
private void WriteTodbLevel() |
|
{ |
|
|
|
Conn.Open(); |
|
try |
|
{ |
|
SQLiteTransaction pTan = Conn.BeginTransaction(); |
|
SQLiteCommand cmd = new SQLiteCommand(Conn); |
|
|
|
cmd.CommandText = "insert into tiles (zoom_level,tile_column,tile_row,tile_data) values(@zoom_level,@tile_column,@tile_row,@tile_data)"; |
|
cmd.Parameters.Add(new SQLiteParameter("@zoom_level", System.Data.DbType.Int32)); |
|
cmd.Parameters.Add(new SQLiteParameter("@tile_column", System.Data.DbType.Int32)); |
|
cmd.Parameters.Add(new SQLiteParameter("@tile_row", System.Data.DbType.Int32)); |
|
cmd.Parameters.Add(new SQLiteParameter("@tile_data", System.Data.DbType.Binary)); |
|
int dealTileCount = 0; |
|
while (dealTileCount < TileCount) |
|
{ |
|
TileInfo[] datas = null; |
|
lock (needInsertDataList) |
|
{ |
|
datas = needInsertDataList.ToArray(); |
|
needInsertDataList.Clear(); |
|
} |
|
if (datas == null || datas.Length == 0) |
|
{ |
|
Thread.Sleep(1000); |
|
} |
|
else |
|
{ |
|
foreach (var item in datas) |
|
{ |
|
if (item.Data == null) |
|
continue; |
|
cmd.Parameters[0].Value = item.Level; |
|
cmd.Parameters[1].Value = item.Column; |
|
cmd.Parameters[2].Value = item.Row; |
|
cmd.Parameters[3].Value = item.Data; |
|
cmd.ExecuteNonQuery(); |
|
item.Data = null; |
|
} |
|
dealTileCount += datas.Length; |
|
if (Report != null) |
|
{ |
|
Report(TileCount, dealTileCount); |
|
} |
|
} |
|
//Thread.Sleep(3000); |
|
Thread.Sleep(0); |
|
} |
|
cmd.CommandText = "CREATE INDEX tiles_index ON tiles (zoom_level,tile_column,tile_row);"; |
|
cmd.ExecuteNonQuery(); |
|
cmd.Dispose(); |
|
pTan.Commit(); |
|
pTan.Dispose(); |
|
if (Done != null) |
|
{ |
|
Done(null, null); |
|
} |
|
|
|
|
|
} |
|
catch (Exception ex) |
|
{ |
|
Console.WriteLine("图片写入db失败:" + ex.Message); |
|
} |
|
finally |
|
{ |
|
Conn.Close(); |
|
Conn.Dispose(); |
|
SQLiteConnection.ClearPool(Conn); |
|
Thread.Sleep(10); |
|
GC.Collect(); |
|
Thread.Sleep(10); |
|
} |
|
} |
|
} |
|
|
|
public class UnionVector |
|
{ |
|
public static Layer UnionVectorLayers(List<Layer> layers, double distance = 100.0) |
|
{ |
|
Layer rstLayer = null; |
|
Geometry rstGeometry = null; |
|
foreach (Layer item in layers) |
|
{ |
|
rstGeometry = UnionGeometry(rstGeometry, UnionVectorLayer(item)); |
|
} |
|
//double distance = 100.0; |
|
//double.TryParse(System.Configuration.ConfigurationManager.AppSettings["BufferDistance"], out distance); |
|
if (rstGeometry == null) return null; |
|
rstGeometry = rstGeometry.Buffer(distance, 30); |
|
OSGeo.OGR.Driver ogrDirver = Ogr.GetDriverByName("Memory"); |
|
DataSource dsLayers = ogrDirver.CreateDataSource("", null); |
|
rstLayer = dsLayers.CreateLayer("", null, wkbGeometryType.wkbPolygon, null); |
|
Feature f = new Feature(rstLayer.GetLayerDefn()); |
|
f.SetGeometry(rstGeometry); |
|
rstLayer.CreateFeature(f); |
|
return rstLayer; |
|
} |
|
|
|
|
|
|
|
public static Geometry UnionVectorLayer(Layer layer) |
|
{ |
|
Feature feature = layer.GetNextFeature(); |
|
if (feature == null) return null; |
|
Geometry rstGeometry = feature.GetGeometryRef(); |
|
while ((feature = layer.GetNextFeature()) != null) |
|
{ |
|
Geometry geo = feature.GetGeometryRef(); |
|
try |
|
{ |
|
rstGeometry = rstGeometry.Union(geo); |
|
} |
|
catch |
|
{ |
|
|
|
} |
|
|
|
} |
|
return rstGeometry; |
|
} |
|
|
|
public static Geometry UnionGeometry(Geometry geometry1, Geometry geometry2) |
|
{ |
|
if (geometry1 == null) |
|
return geometry2; |
|
return geometry1.Union(geometry2); |
|
} |
|
|
|
public static Layer UnionVectorLayers(List<LayerInfo> layerPaths, double distance = 100.0) |
|
{ |
|
|
|
//消除中文路径无法识别的问题 |
|
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); |
|
//解决shape文件字段中文内容读取问题 |
|
OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8"); |
|
List<Layer> layers = new List<Layer>(); |
|
foreach (LayerInfo item in layerPaths) |
|
{ |
|
DataSource dataSource = Ogr.Open(item.LayerSourcePath, 0); |
|
if (string.IsNullOrEmpty(item.LayerName)) |
|
layers.Add(dataSource.GetLayerByIndex(0)); |
|
else |
|
layers.Add(dataSource.GetLayerByName(item.LayerName)); |
|
} |
|
return UnionVectorLayers(layers, distance); |
|
} |
|
|
|
public static Layer CreateLayer(List<Geometry> geometrys, double distance = 100.0) |
|
{ |
|
//消除中文路径无法识别的问题 |
|
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); |
|
//解决shape文件字段中文内容读取问题 |
|
OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8"); |
|
Geometry rstGeometry = null; |
|
foreach (Geometry item in geometrys) |
|
{ |
|
rstGeometry = UnionGeometry(rstGeometry, item); |
|
} |
|
if (rstGeometry == null) return null; |
|
Layer rstLayer = null; |
|
rstGeometry = rstGeometry.Buffer(distance, 30); |
|
OSGeo.OGR.Driver ogrDirver = Ogr.GetDriverByName("Memory"); |
|
DataSource dsLayers = ogrDirver.CreateDataSource("", null); |
|
rstLayer = dsLayers.CreateLayer("", null, wkbGeometryType.wkbPolygon, null); |
|
Feature f = new Feature(rstLayer.GetLayerDefn()); |
|
f.SetGeometry(rstGeometry); |
|
rstLayer.CreateFeature(f); |
|
return rstLayer; |
|
|
|
} |
|
|
|
public static List<FeatureInfo> GetVectorLayerFeatures(List<LayerInfo> layerPaths) |
|
{ |
|
|
|
//消除中文路径无法识别的问题 |
|
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); |
|
//解决shape文件字段中文内容读取问题 |
|
OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8"); |
|
List<FeatureInfo> layers = new List<FeatureInfo>(); |
|
foreach (LayerInfo item in layerPaths) |
|
{ |
|
DataSource dataSource = Ogr.Open(item.LayerSourcePath, 0); |
|
Layer layer = null; |
|
if (string.IsNullOrEmpty(item.LayerName)) |
|
{ |
|
layer = dataSource.GetLayerByIndex(0); |
|
} |
|
else |
|
{ |
|
layer = dataSource.GetLayerByName(item.LayerName); |
|
|
|
} |
|
if (layer != null) |
|
layers.AddRange(GetLayerFeatures(layer)); |
|
} |
|
return layers; |
|
} |
|
|
|
private static List<FeatureInfo> GetLayerFeatures(Layer layer) |
|
{ |
|
List<FeatureInfo> lst = new List<FeatureInfo>(); |
|
Feature feature = layer.GetNextFeature(); |
|
if (feature == null) return null; |
|
int fieldNameIndex = layer.FindFieldIndex("XIJXZQMC", 0); |
|
int fieldCodeIndex = layer.FindFieldIndex("XIJXZQDM", 0); |
|
while ((feature = layer.GetNextFeature()) != null) |
|
{ |
|
FeatureInfo featureInfo = new FeatureInfo(); |
|
if (fieldCodeIndex >= 0) |
|
{ |
|
featureInfo.Code = feature.GetFieldAsString("XIJXZQDM"); |
|
} |
|
if (fieldNameIndex >= 0) |
|
{ |
|
featureInfo.Name = feature.GetFieldAsString("XIJXZQMC"); |
|
} |
|
featureInfo.Shape = feature; |
|
lst.Add(featureInfo); |
|
} |
|
return lst; |
|
} |
|
|
|
public static Layer CreateVectorLayer(FeatureInfo featureInfo) |
|
{ |
|
Layer rstLayer = null; |
|
OSGeo.OGR.Driver ogrDirver = Ogr.GetDriverByName("Memory"); |
|
DataSource dsLayers = ogrDirver.CreateDataSource("", null); |
|
rstLayer = dsLayers.CreateLayer("", null, wkbGeometryType.wkbPolygon, null); |
|
rstLayer.CreateFeature(featureInfo.Shape); |
|
return rstLayer; |
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
/// 获取影像 |
|
/// </summary> |
|
/// <param name="layerInfo"></param> |
|
/// <param name="distance"></param> |
|
/// <returns></returns> |
|
public static List<TileInfo> GetTileInfosByLayer(LayerInfo layerInfo, double distance = 100.0) |
|
{ |
|
DataSource dataSource = null; |
|
Layer layer = null; |
|
try |
|
{ |
|
List<TileInfo> tileInfos = new List<TileInfo>(); |
|
dataSource = Ogr.Open(layerInfo.LayerSourcePath, 0); |
|
if (string.IsNullOrEmpty(layerInfo.LayerName)) |
|
layer = dataSource.GetLayerByIndex(0); |
|
else |
|
layer = dataSource.GetLayerByName(layerInfo.LayerName); |
|
|
|
Feature feature = null; |
|
OSGeo.OGR.Envelope geoEnvelope = new OSGeo.OGR.Envelope(); |
|
while ((feature = layer.GetNextFeature()) != null) |
|
{ |
|
Geometry geo = feature.GetGeometryRef(); |
|
geo = geo.Buffer(distance, 30); |
|
geo.GetEnvelope(geoEnvelope); |
|
if (geoEnvelope != null) |
|
{ |
|
Envelope e = new Envelope() |
|
{ |
|
XMin = geoEnvelope.MinX, |
|
YMin = geoEnvelope.MinY, |
|
XMax = geoEnvelope.MaxX, |
|
YMax = geoEnvelope.MaxY |
|
}; |
|
tileInfos.Add(new TileInfo(e, 0, 0, 0)); |
|
geoEnvelope.Dispose(); |
|
geoEnvelope = new OSGeo.OGR.Envelope(); |
|
} |
|
} |
|
|
|
return tileInfos; |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
finally |
|
{ |
|
if (dataSource != null) |
|
{ |
|
dataSource.Dispose(); |
|
} |
|
if (layer != null) |
|
{ |
|
layer.Dispose(); |
|
} |
|
} |
|
|
|
} |
|
} |
|
|
|
public class LayerInfo |
|
{ |
|
public string LayerSourcePath { get; set; } |
|
public string LayerName { get; set; } |
|
public int LayerIndex { get; set; } |
|
} |
|
|
|
public class FeatureInfo |
|
{ |
|
public string Name { get; set; } |
|
public string Code { get; set; } |
|
public Feature Shape { get; set; } |
|
} |
|
|
|
public enum EnumSaveType |
|
{ |
|
Level = 0, Resolution = 1 |
|
} |
|
|
|
|
|
}
|
|
|