Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added CRS indexing based on an sqlite database #108

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
10 changes: 8 additions & 2 deletions ProjNet4GeoAPI.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29020.237
# Visual Studio Version 17
VisualStudioVersion = 17.4.33103.184
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNET", "src\ProjNet\ProjNET.csproj", "{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}"
EndProject
Expand All @@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNET.Tests", "test\ProjN
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNet.Benchmark", "src\ProjNet.Benchmark\ProjNet.Benchmark.csproj", "{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNet.Sqlite", "src\ProjNet.Sqlite\ProjNet.Sqlite.csproj", "{3D364E7E-7D2D-42FB-A62B-137BBA2F8F1E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -33,6 +35,10 @@ Global
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Release|Any CPU.Build.0 = Release|Any CPU
{3D364E7E-7D2D-42FB-A62B-137BBA2F8F1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D364E7E-7D2D-42FB-A62B-137BBA2F8F1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D364E7E-7D2D-42FB-A62B-137BBA2F8F1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D364E7E-7D2D-42FB-A62B-137BBA2F8F1E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Binary file added src/.DS_Store
Binary file not shown.
Binary file added src/ProjNet.Sqlite/.DS_Store
Binary file not shown.
66 changes: 66 additions & 0 deletions src/ProjNet.Sqlite/CoordinateSystemInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using SQLite;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProjNet.IO
{
/// <summary>
/// Model for coordinate system in the database
/// </summary>
[Table("srs_data")]
public class CoordinateSystemInfo
{
/// <summary>
///
/// </summary>
public string Authority { get; set; }
/// <summary>
///
/// </summary>
[PrimaryKey]
public int Code { get; set; }
/// <summary>
///
/// </summary>
public string Name { get; set; }
/// <summary>
///
/// </summary>
public string Alias { get; set; }
/// <summary>
///
/// </summary>
public bool IsDeprecated { get; set; }
/// <summary>
///
/// </summary>
[Column("type")]
public string SystemType { get; set; }
/// <summary>
///
/// </summary>
public string WKT { get; set; }

/// <summary>
/// Parameterless construction for initialization
/// </summary>
public CoordinateSystemInfo()
{
}

/// <summary>
/// Holds info about the coordinate system
/// </summary>
public CoordinateSystemInfo(string name, string alias, string authority, int code, string systemType, bool isDeprecated, string wkt)
{
Authority = authority;
Code = code;
Name = name;
Alias = alias;
SystemType = systemType;
IsDeprecated = isDeprecated;
WKT = wkt;
}
}
}
148 changes: 148 additions & 0 deletions src/ProjNet.Sqlite/DatabaseCoordinateService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
using ProjNet.CoordinateSystems;
using ProjNet.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace ProjNet.Services
{
/// <summary>
/// Coordinate System Service tied to a database
/// </summary>
public class DatabaseCoordinateService : CoordinateSystemService, ICoordinateSystemService
{
private readonly DatabaseProvider _dbProvider;

/// <summary>
/// Initializes a DatabaseCoordinateService to retreive
/// Coordinate Systems from an internal database
/// </summary>
public DatabaseCoordinateService(CoordinateSystemFactory csFactory)
: base(csFactory)
{
_dbProvider = new DatabaseProvider();
}

/// <summary>
/// Initializes a DatabaseCoordinateService to retreive
/// Coordinate Systems from an internal database
/// </summary>
public DatabaseCoordinateService()
: this(new CoordinateSystemFactory())
{
_dbProvider = new DatabaseProvider();
}

#region Interface Methods
/// <summary>
/// Returns the coordinate system by <paramref name="srid" /> identifier
/// </summary>
/// <param name="srid">The initialization for the coordinate system</param>
/// <returns>The coordinate system.</returns>
public CoordinateSystem GetCoordinateSystem(int srid)
{
var sysInfo = _dbProvider.GetCoordinateSystemInfo(srid).Result;
if (sysInfo != null)
return CsFactory.CreateFromWkt(sysInfo.WKT);

return null;
}

/// <summary>
/// Returns the coordinate system by <paramref name="srid" /> identifier
/// </summary>
/// <param name="srid">The initialization for the coordinate system</param>
/// <returns>The coordinate system.</returns>
public async Task<CoordinateSystem> GetCoordinateSystemAsync(int srid)
{
var sysInfo = await _dbProvider.GetCoordinateSystemInfo(srid);
if (sysInfo != null)
return CsFactory.CreateFromWkt(sysInfo.WKT);

return null;
}

/// <summary>
/// Returns the coordinate system by <paramref name="authority" /> and <paramref name="code" />.
/// </summary>
/// <param name="authority">The authority for the coordinate system</param>
/// <param name="code">The code assigned to the coordinate system by <paramref name="authority" />.</param>
/// <returns>The coordinate system.</returns>
public CoordinateSystem GetCoordinateSystem(string authority, long code)
{

int? srid = GetSRID(authority, code);
if (srid.HasValue)
return GetCoordinateSystem(srid.Value);
return null;
}

/// <summary>
/// Searches the table names based on an expression
/// </summary>
/// <param name="name"></param>
public Task<IEnumerable<CoordinateSystemInfo>> SearchCoordinateSystemAsync(string name)
{
return _dbProvider.SearchCoordinateSystemAsync(name);

}

/// <summary>
/// Method to get the identifier, by which this coordinate system can be accessed.
/// </summary>
/// <param name="authority">The authority name</param>
/// <param name="authorityCode">The code assigned by <paramref name="authority" /></param>
/// <returns>The identifier or <value>null</value></returns>
public int? GetSRID(string authority, long authorityCode)
{
return (int)authorityCode;
}

/// <summary>
/// Returns number of coordinate systems registered by the service
/// </summary>
public int Count => _dbProvider.GetCount().Result;

/// <summary>
/// Adds a coordinate system to the dictionary based on srid
/// </summary>
/// <param name="srid"></param>
/// <param name="coordinateSystem"></param>
public void AddCoordinateSystem(int srid, CoordinateSystem coordinateSystem)
{
if (coordinateSystem.Name == null)
throw new ArgumentNullException("Name is null.");
if (coordinateSystem.AuthorityCode <= 0)
coordinateSystem.AuthorityCode = srid;
if (string.IsNullOrEmpty(coordinateSystem.Authority))
coordinateSystem.Authority = "EPSG";
if (string.IsNullOrEmpty(coordinateSystem.Alias))
coordinateSystem.Alias = coordinateSystem.Name;

AddCoordinateSystem(coordinateSystem);
}

/// <summary>
/// Adds a coordinate system to the dictionary.
/// The authority code is defaulted as the srid.
/// </summary>
/// <param name="coordinateSystem"></param>
/// <returns></returns>
public int AddCoordinateSystem(CoordinateSystem coordinateSystem)
{
return _dbProvider.AddCoordinateSystem(coordinateSystem).Result;
}

/// <summary>
/// Removes a coordinate system from the database
/// </summary>
public bool RemoveCoordinateSystem(int srid)
{
return _dbProvider.RemoveCoordinateSystem(srid).Result;
}
#endregion
}
}
151 changes: 151 additions & 0 deletions src/ProjNet.Sqlite/DatabaseProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using ProjNet.CoordinateSystems;
using ProjNet.IO.CoordinateSystems;
using ProjNet.Sqlite.Extensions;
using SQLite;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace ProjNet.IO
{
/// <summary>
/// Handles calls to the database
/// </summary>
public class DatabaseProvider
{
private string _connectionString;
SQLiteAsyncConnection Database;

/// <summary>
/// Creates an instance of the DatabaseProvider
/// </summary>
public DatabaseProvider()
{
string currentDir = AppContext.BaseDirectory;
_connectionString = Path.Combine(currentDir, "proj.db");
}

/// <summary>
/// Creates an instance of the DatabaseProvider
/// </summary>
public DatabaseProvider(string database)
{
_connectionString = database;
}

/// <summary>
/// Initializes the Database
/// </summary>
/// <returns></returns>
async Task Init()
{
if (Database is not null)
return;

Database = new SQLiteAsyncConnection(_connectionString, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.SharedCache);
var result = await Database.CreateTableAsync<CoordinateSystemInfo>();
}

/// <summary>
/// Returns the coordinate info base on the code
/// </summary>
/// <param name="srid">the code to retrieve</param>
public async Task<CoordinateSystemInfo> GetCoordinateSystemInfo(int srid)
{
await Init();
return await Database.Table<CoordinateSystemInfo>().Where(i => i.Code == srid).FirstOrDefaultAsync();
}

/// <summary>
/// Searches the table names based on an expression
/// </summary>
/// <param name="searchKey"></param>
public async Task<IEnumerable<CoordinateSystemInfo>> SearchCoordinateSystemAsync(string searchKey)
{
await Init();
var filters = searchKey.ToLower().Split(' ').ToList();

return await Like(filters);
}

private async Task<IEnumerable<CoordinateSystemInfo>> Like(List<string> filters)
{
var data =await Database.Table<CoordinateSystemInfo>().ToArrayAsync();
foreach (string filter in filters)
data = data.Where(x => x.Name.ToLower().Contains(filter)).ToArray();

return data;
}

/// <summary>
/// Returns the number of entries in the database
/// </summary>
internal async Task<int> GetCount()
{
await Init();
return await Database.Table<CoordinateSystemInfo>().CountAsync();
}

/// <summary>
/// Adds a coordinate system to the database
/// </summary>
internal async Task<int> AddCoordinateSystem(CoordinateSystem coordinateSystem)
{
var coordType = GetSystemType(coordinateSystem.WKT);
var coordInfo = new CoordinateSystemInfo(coordinateSystem.Name, coordinateSystem.Alias,
coordinateSystem.Authority, (int)coordinateSystem.AuthorityCode,
coordType.ToString(), false, coordinateSystem.WKT);

return await AddCoordinateSystem(coordInfo);
}

internal async Task<int> AddCoordinateSystem(CoordinateSystemInfo coordinateInfo)
{
await Init();
return await Database.InsertAsync(coordinateInfo);
}

/// <summary>
/// Removes a coordninate system from the database
/// </summary>

internal async Task<bool> RemoveCoordinateSystem(int srid)
{
await Init();
var csInfo = await GetCoordinateSystemInfo(srid);
if (csInfo != null)
return await Database.DeleteAsync(csInfo) > 0;

return false;
}

/// <summary>
/// Parses the wkt to get the appropriate CoordinateSystemType
/// </summary>
private CoordinateSystemType GetSystemType(string wkt)
{
int bracket = wkt.IndexOf("[");
if (bracket >= 0)
{
string coordType = wkt.Substring(0, bracket);
switch (coordType)
{
case "PROJCS":
return CoordinateSystemType.projected;
case "GEOGCS":
return CoordinateSystemType.geographic2D;
case "COMPD_CS":
return CoordinateSystemType.compound;
case "VERT_CS":
return CoordinateSystemType.vertical;
}
}

return CoordinateSystemType.unknown;
}


}
}
Loading