kopia lustrzana https://github.com/dl2alf/AirScout
271 wiersze
12 KiB
C#
271 wiersze
12 KiB
C#
using ScoutBase.Core;
|
|
using ScoutBase.Elevation;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
using GMap.NET;
|
|
using GMap.NET.WindowsForms;
|
|
using GMap.NET.MapProviders;
|
|
using System.Data.SQLite;
|
|
using System.IO;
|
|
using System.Data;
|
|
using ScoutBase.Maps;
|
|
using System.Net;
|
|
|
|
namespace AirScout
|
|
{
|
|
public partial class MapDlg : Form
|
|
{
|
|
|
|
#region MapPreloader
|
|
|
|
class MapPreloaderTile
|
|
{
|
|
public int X;
|
|
public int Y;
|
|
public int Z;
|
|
public int Type;
|
|
|
|
public MapPreloaderTile(int x, int y, int z, int type)
|
|
{
|
|
X = x;
|
|
Y = y;
|
|
Z = z;
|
|
Type = type;
|
|
}
|
|
}
|
|
|
|
// Background worker for preloading of map tiles
|
|
[DefaultPropertyAttribute("Name")]
|
|
public class MapPreloader : BackgroundWorker
|
|
{
|
|
string Name = "MapPreloader";
|
|
ELEVATIONMODEL Model = ELEVATIONMODEL.NONE;
|
|
GMapControl gm_Map = new GMapControl();
|
|
System.Data.SQLite.SQLiteDatabase db;
|
|
|
|
public MapPreloader()
|
|
{
|
|
this.WorkerReportsProgress = true;
|
|
this.WorkerSupportsCancellation = true;
|
|
}
|
|
|
|
int long2tilex(double lon, int z)
|
|
{
|
|
return (int)(Math.Floor((lon + 180.0) / 360.0 * (1 << z)));
|
|
}
|
|
|
|
int lat2tiley(double lat, int z)
|
|
{
|
|
return (int)Math.Floor((1 - Math.Log(Math.Tan((lat / 180.0 * Math.PI)) + 1 / Math.Cos((lat / 180.0 * Math.PI))) / Math.PI) / 2 * (1 << z));
|
|
}
|
|
|
|
double tilex2long(int x, int z)
|
|
{
|
|
return x / (double)(1 << z) * 360.0 - 180;
|
|
}
|
|
|
|
double tiley2lat(int y, int z)
|
|
{
|
|
double n = Math.PI - 2.0 * Math.PI * y / (double)(1 << z);
|
|
return 180.0 / Math.PI * Math.Atan(0.5 * (Math.Exp(n) - Math.Exp(-n)));
|
|
}
|
|
|
|
private bool LoadOSM (int x, int y , int zoom)
|
|
{
|
|
bool b = false;
|
|
string url = ScoutBase.Maps.Properties.Settings.Default.Database_UpdateURL + zoom.ToString() + "/" + x.ToString() + "/" + y.ToString() + ".png";
|
|
string filename = Path.Combine(Path.GetTempPath(), y.ToString() + ".png");
|
|
try
|
|
{
|
|
WebClient cl = new WebClient();
|
|
cl.DownloadFile(url, filename);
|
|
using (BinaryReader br = new BinaryReader(File.OpenRead(filename)))
|
|
{
|
|
byte[] buf = br.ReadBytes((int)br.BaseStream.Length);
|
|
// int id = MapData.Database.TileInsert(x, y, zoom, gm_Map.MapProvider.DbId, File.GetLastWriteTime(filename), buf);
|
|
int dbid = GMapProviders.OpenStreetMap.DbId;
|
|
GMaps.Instance.EnqueueCacheTask(new GMap.NET.Internals.CacheQueueItem(new GMap.NET.Internals.RawTile(dbid, new GPoint(x, y), zoom), buf,GMap.NET.Internals.CacheUsage.First));
|
|
}
|
|
File.Delete(filename);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(this.Name + ": " + ex.ToString());
|
|
}
|
|
return b;
|
|
}
|
|
|
|
protected override void OnDoWork(DoWorkEventArgs e)
|
|
{
|
|
BACKGROUNDUPDATERSTARTOPTIONS Options = (BACKGROUNDUPDATERSTARTOPTIONS)e.Argument;
|
|
// name the thread for debugging
|
|
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
|
|
Thread.CurrentThread.Name = this.Name + "_" + this.GetType().Name;
|
|
this.ReportProgress(0, this.Name + " started.");
|
|
Log.WriteMessage(this.Name + " started.");
|
|
// get update interval
|
|
int interval = (int)Properties.Settings.Default.Background_Update_Period * 60;
|
|
// get mpst simple elevation model
|
|
if (Properties.Settings.Default.Elevation_GLOBE_Enabled)
|
|
Model = ELEVATIONMODEL.GLOBE;
|
|
else if (Properties.Settings.Default.Elevation_SRTM3_Enabled)
|
|
Model = ELEVATIONMODEL.SRTM3;
|
|
else if (Properties.Settings.Default.Elevation_SRTM1_Enabled)
|
|
Model = ELEVATIONMODEL.SRTM1;
|
|
// return if no elevation model selected
|
|
if (Model == ELEVATIONMODEL.NONE)
|
|
return;
|
|
// setting User Agent to fix Open Street Map issue 2016-09-20
|
|
GMap.NET.MapProviders.GMapProvider.UserAgent = "AirScout";
|
|
// clearing referrer URL issue 2019-12-14
|
|
gm_Map.MapProvider.RefererUrl = "";
|
|
// set initial settings for main map
|
|
gm_Map.MapProvider = GMapProviders.Find(Properties.Settings.Default.Map_Provider);
|
|
gm_Map.MinZoom = 0;
|
|
gm_Map.MaxZoom = 20;
|
|
// get database filename
|
|
int i = 0;
|
|
int count = 0;
|
|
int total = 0;
|
|
do
|
|
{
|
|
i = 0;
|
|
count = 0;
|
|
total = 0;
|
|
// checks if elevation database is complete
|
|
try
|
|
{
|
|
this.ReportProgress(0, this.Name + " getting tiles from database.");
|
|
int zmin = 5;
|
|
int zmax = 11;
|
|
List<MapPreloaderTile> l = new List<MapPreloaderTile>();
|
|
for (int z = zmin; z <= zmax; z++)
|
|
{
|
|
int xmin = long2tilex(Properties.Settings.Default.MinLon, z);
|
|
int xmax = long2tilex(Properties.Settings.Default.MaxLon, z);
|
|
int ymin = lat2tiley(Properties.Settings.Default.MaxLat, z);
|
|
int ymax = lat2tiley(Properties.Settings.Default.MinLat, z);
|
|
for (int x = xmin; x <= xmax; x++)
|
|
{
|
|
for (int y = ymin; y <= ymax; y++)
|
|
{
|
|
// check if tile already in database --> add it to list to get it from the web
|
|
if (!MapData.Database.TileExists(x, y, z, gm_Map.MapProvider.DbId))
|
|
{
|
|
MapPreloaderTile t = new MapPreloaderTile(x, y, z, gm_Map.MapProvider.DbId);
|
|
l.Add(t);
|
|
}
|
|
total++;
|
|
if (this.CancellationPending)
|
|
break;
|
|
}
|
|
if (this.CancellationPending)
|
|
break;
|
|
}
|
|
if (this.CancellationPending)
|
|
break;
|
|
}
|
|
if (this.CancellationPending)
|
|
break;
|
|
count = l.Count();
|
|
Random rng = new Random();
|
|
// shuffle the list
|
|
int n = l.Count;
|
|
while (n > 1)
|
|
{
|
|
n--;
|
|
int k = rng.Next(n + 1);
|
|
MapPreloaderTile value = l[k];
|
|
l[k] = l[n];
|
|
l[n] = value;
|
|
}
|
|
n = 0;
|
|
foreach (MapPreloaderTile t in l)
|
|
{
|
|
Exception ex = null;
|
|
this.ReportProgress(0, "Preloading " + "/" + t.Z.ToString() + "/" + t.X.ToString() + "/" + t.Y.ToString() + ".png");
|
|
try
|
|
{
|
|
// try to donwload from www.airscout.eu first
|
|
if (gm_Map.MapProvider.GetType() == typeof(OpenStreetMapProvider))
|
|
{
|
|
LoadOSM(t.X, t.Y, t.Z);
|
|
}
|
|
else
|
|
{
|
|
PureImage img = gm_Map.Manager.GetImageFrom(gm_Map.MapProvider, new GPoint(t.X, t.Y), t.Z, out ex);
|
|
// wait until cache is written to database
|
|
}
|
|
if (ex == null)
|
|
Console.WriteLine("Preload tile [" + i.ToString() + " of " + count.ToString() + "] x=" + t.X + ", y=" + t.Y + ", z=" + t.Z + ": OK");
|
|
else
|
|
Console.WriteLine("Preload tile [" + i.ToString() + " of " + count.ToString() + "] x=" + t.X + ", y=" + t.Y + ", z=" + t.Z + ": " + ex.ToString());
|
|
}
|
|
catch (Exception e1)
|
|
{
|
|
Console.WriteLine(this.Name + ": " + e1.ToString());
|
|
}
|
|
Thread.Sleep(100);
|
|
i++;
|
|
n++;
|
|
if (n > 100)
|
|
{
|
|
while (GMaps.Instance.tileCacheQueue.Count > 0)
|
|
{
|
|
Application.DoEvents();
|
|
if (this.CancellationPending)
|
|
break;
|
|
}
|
|
n = 0;
|
|
}
|
|
if (this.CancellationPending)
|
|
break;
|
|
}
|
|
if (this.CancellationPending)
|
|
break;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
this.ReportProgress(-1, ex.ToString());
|
|
}
|
|
|
|
// sleep when running periodically
|
|
if (Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY)
|
|
{
|
|
int l = 0;
|
|
while (!this.CancellationPending && (l < interval))
|
|
{
|
|
Thread.Sleep(1000);
|
|
l++;
|
|
}
|
|
}
|
|
if (this.CancellationPending)
|
|
break;
|
|
}
|
|
while (Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY);
|
|
if (this.CancellationPending)
|
|
{
|
|
this.ReportProgress(0, Name + " cancelled.");
|
|
Log.WriteMessage(Name + " cancelled.");
|
|
}
|
|
else
|
|
{
|
|
this.ReportProgress(0, Name + " finished, total " + total.ToString() + " tile(s), " + (count-i).ToString() + " left.");
|
|
Log.WriteMessage(Name + " finished, total " + total.ToString() + " tile(s), " + (count - i).ToString() + " left.");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|