|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|