年度变更建库软件5.0版本
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.
 
 

277 lines
10 KiB

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SQLite;
using System.Threading;
namespace Kingo.Plugin.MakeTaskPackage.Entity
{
public delegate void ProgressReport(int sum, int current);
public class WriteTilesToDataBase : IDisposable
{
public event ProgressReport Report;
public SQLiteConnection Conn { get; set; }
public int TileCount { get; set; }
public int BlankImageSize { get; set; }
private List<TileInfo> needInsertDataList = new List<TileInfo>();
public void InsertData(TileInfo data)
{
lock (needInsertDataList)
{
needInsertDataList.Add(data);
}
}
public void InsertDataRange(TileInfo[] data)
{
lock (needInsertDataList)
{
needInsertDataList.AddRange(data);
}
}
Thread doworkThread = null;
public void DoWork()
{
doworkThread = new Thread(new ThreadStart(DoWork2));
doworkThread.IsBackground = true;
//doworkThread.SetApartmentState(ApartmentState.STA);
doworkThread.Name = "写入图片线程" + Guid.NewGuid().ToString();
//doworkThread.Priority = ThreadPriority.AboveNormal;
doworkThread.Start();
}
private void DoWork2()
{
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)
{
//Console.WriteLine("Sleep");
Thread.Sleep(1000);
}
else
{
Console.WriteLine("record:" + datas.Length.ToString());
foreach (var item in datas)
{
if (item.Data == null || item.Data.Length == BlankImageSize)//
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(0);
}
cmd.CommandText = "CREATE INDEX tiles_index ON tiles (zoom_level,tile_column,tile_row);";
try
{
cmd.ExecuteNonQuery();
}
catch
{
}
pTan.Commit();
if (Done != null)
{
Done(null, null);
}
}
finally
{
Conn.Close();
Conn.Dispose();
SQLiteConnection.ClearPool(Conn);
Thread.Sleep(10);
GC.Collect();
Thread.Sleep(10);
}
}
public void DoWorkLevel()
{
doworkThread = new Thread(new ThreadStart(DoWork2Level));
doworkThread.IsBackground = true;
//doworkThread.SetApartmentState(ApartmentState.STA);
doworkThread.Name = "写入图片线程" + Guid.NewGuid().ToString();
//doworkThread.Priority = ThreadPriority.AboveNormal;
doworkThread.Start();
}
private void DoWork2Level()
{
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,maxX,maxY,minX,minY,resolution) values(@zoom_level,@tile_column,@tile_row,@tile_data,@maxX,@maxY,@minX,@minY,@resolution)";
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));
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));
int dealTileCount = 0;
while (dealTileCount < TileCount)
{
TileInfo[] datas = null;
lock (needInsertDataList)
{
datas = needInsertDataList.ToArray();
needInsertDataList.Clear();
}
if (datas == null || datas.Length == 0)
{
//Console.WriteLine("Sleep");
Thread.Sleep(1000);
}
else
{
//Console.WriteLine("record:" + datas.Length.ToString());
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.Parameters[4].Value = item.Bound.XMax;
cmd.Parameters[5].Value = item.Bound.YMax;
cmd.Parameters[6].Value = item.Bound.XMin;
cmd.Parameters[7].Value = item.Bound.YMin;
cmd.Parameters[8].Value = item.Resolution;
cmd.ExecuteNonQuery();
item.Data = null;
}
dealTileCount += datas.Length;
if (Report != null)
{
Report(TileCount, dealTileCount);
}
}
Thread.Sleep(0);
}
try
{
cmd.CommandText = "CREATE INDEX tiles_index ON tiles (zoom_level,tile_column,tile_row);";
cmd.ExecuteNonQuery();
cmd.CommandText = "CREATE INDEX bound_index ON tiles (maxX,maxY,minX,minY,resolution);";
cmd.ExecuteNonQuery();
}
catch
{
}
pTan.Commit();
if (Done != null)
{
Done(null, null);
}
}
finally
{
Conn.Close();
Conn.Dispose();
SQLiteConnection.ClearPool(Conn);
Thread.Sleep(10);
GC.Collect();
Thread.Sleep(10);
}
}
public event EventHandler Done;
public void Stop()
{
Dispose();
}
public void Dispose()
{
if (doworkThread != null)
{
try
{
doworkThread.Abort();
}
catch
{
}
finally
{
doworkThread = null;
}
}
}
private const double EARTH_RADIUS = 6378137;
/// <summary>
/// 计算两点位置的距离,返回两点的距离,单位 米
/// 该公式为GOOGLE提供,误差小于0.2米
/// </summary>
/// <param name="lat1">第一点纬度</param>
/// <param name="lng1">第一点经度</param>
/// <param name="lat2">第二点纬度</param>
/// <param name="lng2">第二点经度</param>
/// <returns></returns>
public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
{
double radLat1 = Rad(lat1);
double radLng1 = Rad(lng1);
double radLat2 = Rad(lat2);
double radLng2 = Rad(lng2);
double a = radLat1 - radLat2;
double b = radLng1 - radLng2;
double result = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))) * EARTH_RADIUS;
return result;
}
/// <summary>
/// 经纬度转化成弧度
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
private static double Rad(double d)
{
return (double)d * Math.PI / 180d;
}
}
}