从 sqlite 数据库中读取轨迹数据,存储到 postgis 数据库中,再利用 postgis 的特性进行轨迹分析。
Program.cs
class Program
{
static void Main(string[] args)
{
List<Track> tracks = new List<Track>();
try
{
#region 从Sqlite中读取轨迹数据
//Sqlite数据库路径
string sqlitePath = Path.Combine(Environment.CurrentDirectory, "track.db");
//数据表名称
string sqliteTb = "T_1140204000334";
using (SqliteDB sqlite = new SqliteDB(sqlitePath))
{
sqlite.Open();
DataTable dt = sqlite.ExecuteSQL("select * from " + sqliteTb + ";");
if (dt != null && dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
tracks.Add(new Track()
{
B = Convert.ToDouble(dt.Rows[i]["B"]) * 180 / Math.PI,
L = Convert.ToDouble(dt.Rows[i]["L"]) * 180 / Math.PI,
H = Convert.ToSingle(dt.Rows[i]["H"]),
Azi = Convert.ToSingle(dt.Rows[i]["Azi"]),
AntH = Convert.ToSingle(dt.Rows[i]["AntH"]),
UTCTime = Convert.ToDateTime(dt.Rows[i]["UTCTime"]),
Hdop = Convert.ToSingle(dt.Rows[i]["Hdop"]),
SolType = Convert.ToInt32(Convert.ToByte(dt.Rows[i]["SolType"]))
});
}
}
}
Console.WriteLine("Sqlite中的轨迹记录数为:" + tracks.Count);
Console.WriteLine("---------------------------------------------------------------------");
#endregion
#region 向PostgreSQL中存入轨迹数据
using (PostgresqlDB postgresql = new PostgresqlDB("localhost", "5432", "postgres", "123456", "test"))
{
postgresql.Open();
string tableName = "t_1_1_20150519103523";
StringBuilder sql = new StringBuilder();
#region 写入数据
//删除数据表
if (postgresql.QueryTableIsExist(tableName))
{
sql.Clear();
sql.AppendLine("drop table " + tableName + ";");
postgresql.ExecuteNonQuery(sql.ToString());
}
postgresql.BeginTransaction();
try
{
//创建数据表
sql.Clear();
sql.AppendLine("create table " + tableName + "(");
sql.AppendLine("id serial not null,");
sql.AppendLine("coord geometry(point, 4326) not null,");
sql.AppendLine("h real not null,");
sql.AppendLine("azi real not null,");
sql.AppendLine("ant_h real not null,");
sql.AppendLine("utc_time timestamp with time zone not null,");
sql.AppendLine("hdop real not null,");
sql.AppendLine("sol_type integer not null,");
sql.AppendLine("constraint " + tableName + "_pkey primary key (id)");
sql.AppendLine(");");
postgresql.ExecuteNonQuery(sql.ToString());
//插入记录
for (int i = 0; i < tracks.Count; i++)
{
sql.Clear();
sql.AppendLine("insert into " + tableName + "(coord,h,azi,ant_h,utc_time,hdop,sol_type) values(");
sql.AppendLine(string.Format("ST_GeomFromText('point({0} {1})',4326),", tracks[i].B, tracks[i].L));
sql.AppendLine(tracks[i].H + ",");
sql.AppendLine(tracks[i].Azi + ",");
sql.AppendLine(tracks[i].AntH + ",");
sql.AppendLine("'" + tracks[i].UTCTime.ToString("yyyy-MM-dd HH:mm:ss") + "',");
sql.AppendLine(tracks[i].Hdop + ",");
sql.AppendLine(tracks[i].SolType.ToString());
sql.AppendLine(");");
postgresql.ExecuteNonQuery(sql.ToString());
}
postgresql.Commit();
Console.WriteLine("写入postgresql成功!");
Console.WriteLine("---------------------------------------------------------------------");
}
catch (Exception ex)
{
postgresql.Rollback();
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
postgresql.EndTransaction();
#endregion
#region 读取数据
tracks.Clear();
DataTable dt = postgresql.ExecuteQuery("select st_x(coord) as b, st_y(coord) as l, h, azi, ant_h, utc_time, hdop, sol_type from " + tableName + ";");
if (dt != null && dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
tracks.Add(new Track() {
B = Convert.ToDouble(dt.Rows[i]["b"]),
L = Convert.ToDouble(dt.Rows[i]["l"]),
H = Convert.ToSingle(dt.Rows[i]["h"]),
Azi = Convert.ToSingle(dt.Rows[i]["azi"]),
AntH = Convert.ToSingle(dt.Rows[i]["ant_h"]),
UTCTime = Convert.ToDateTime(dt.Rows[i]["utc_time"]),
Hdop = Convert.ToSingle(dt.Rows[i]["hdop"]),
SolType = Convert.ToInt32(dt.Rows[i]["sol_type"])
});
}
}
Console.WriteLine("读取postgresql中的数据成功!记录数为:" + tracks.Count);
Console.WriteLine("---------------------------------------------------------------------");
#endregion
#region 轨迹分析
//轨迹总长度
double dist = 0;
DataTable dtDistance = postgresql.ExecuteQuery("select st_length(st_makeline(st_transform(coord, 4504))) from " + tableName + ";");
if (dtDistance != null && dtDistance.Rows.Count > 0)
{
dist = Convert.ToDouble(dtDistance.Rows[0][0]);
Console.WriteLine("轨迹总长度:" + dist + " 米");
Console.WriteLine("---------------------------------------------------------------------");
}
//轨迹总时间
double seconds = 0;
DataTable dtDateTime = postgresql.ExecuteQuery("select max(utc_time), min(utc_time) from " + tableName + ";");
if (dtDateTime != null && dtDateTime.Rows.Count > 0)
{
DateTime max = Convert.ToDateTime(dtDateTime.Rows[0][0]);
DateTime min = Convert.ToDateTime(dtDateTime.Rows[0][1]);
seconds = (max - min).TotalSeconds;
Console.WriteLine("轨迹总时间:" + seconds + " 秒");
Console.WriteLine("---------------------------------------------------------------------");
}
//轨迹平均速度
if (seconds != 0)
{
Console.WriteLine("轨迹平均速度:" + dist / seconds + " 米/秒");
Console.WriteLine("---------------------------------------------------------------------");
}
//轨迹瞬时速度(计算相邻两条记录的距离及时间间隔)
//extract(epoch from time1-time2):计算时间间隔的总秒数
DataTable dtDelta = postgresql.ExecuteQuery("select st_distance(st_transform(p1.coord,4504),st_transform(p2.coord,4504)) as delta_d, extract(epoch from p1.utc_time-p2.utc_time) as delta_t from " + tableName + " as p1, " + tableName + " as p2 where p1.id = p2.id+1;");
if (dtDelta != null && dtDelta.Rows.Count > 0)
{
double delta_d = Convert.ToDouble(dtDelta.Rows[dtDelta.Rows.Count - 1]["delta_d"]);
double delta_t = Convert.ToDouble(dtDelta.Rows[dtDelta.Rows.Count - 1]["delta_t"]);
if (delta_t != 0)
{
Console.WriteLine("最后一个点的分析结果为:\r\n 瞬时位移:" + delta_d + " 米" +
"\r\n 时间间隔:" + delta_t + " 秒" +
"\r\n 瞬时速度:" + delta_d / delta_t + " 米/秒");
Console.WriteLine("---------------------------------------------------------------------");
}
}
#endregion
}
#endregion
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.Read();
}
}
运行结果为:
Sqlite中的轨迹记录数为:1521
---------------------------------------------------------------------
写入postgresql成功!
---------------------------------------------------------------------
读取postgresql中的数据成功!记录数为:1521
---------------------------------------------------------------------
轨迹总长度:16775.455657666 米
---------------------------------------------------------------------
轨迹总时间:353325 秒
---------------------------------------------------------------------
轨迹平均速度:0.0474788244751037 米/秒
---------------------------------------------------------------------
最后一个点的分析结果为:
瞬时位移:5.32844146492802 米
时间间隔:1 秒
瞬时速度:5.32844146492802 米/秒
---------------------------------------------------------------------
Track.cs
public class Track
{
public double B;
public double L;
public float H;
public float Azi;
public float AntH;
public DateTime UTCTime;
public float Hdop;
public int SolType;
}
SqliteDB.cs
/// <summary>
/// Sqlite数据库操作类
/// </summary>
public class SqliteDB : IDisposable
{
#region 字段
/// <summary>
/// 数据库连接字符串构造器
/// </summary>
private SQLiteConnectionStringBuilder _connStr = null;
/// <summary>
/// 数据库连接器
/// </summary>
private SQLiteConnection _conn = null;
/// <summary>
/// 通过连接器创建NpgsqlCommand对象,用于执行SQL语句
/// </summary>
private SQLiteCommand _comm = null;
/// <summary>
/// 事务管理对象
/// </summary>
private SQLiteTransaction _trans = null;
#endregion
#region 构造函数
public SqliteDB(string filePath)
{
_connStr = new SQLiteConnectionStringBuilder();
_connStr.DataSource = filePath;
_conn = new SQLiteConnection(_connStr.ToString());
_comm = _conn.CreateCommand();
}
~SqliteDB()
{
}
#endregion
#region 静态方法
/// <summary>
/// 创建数据库
/// </summary>
/// <param name="filePath">db文件路径+文件名</param>
public static void CreateDB(string filePath)
{
try
{
SQLiteConnection.CreateFile(filePath);
}
catch
{
throw;
}
}
#endregion
#region 公共方法
#region 数据库操作:连接数据库、断开数据库、加密数据库
/// <summary>
/// 打开数据库连接
/// </summary>
/// <returns>是否连接成功</returns>
public bool Open()
{
try
{
_conn.Open();
return true;
}
catch
{
Close();
return false;
throw;
}
}
/// <summary>
/// 打开数据库连接
/// </summary>
/// <param name="password">密码</param>
/// <returns>是否连接成功</returns>
public bool Open(string password)
{
try
{
_conn.SetPassword(password);
_conn.Open();
return true;
}
catch
{
Close();
return false;
throw;
}
}
/// <summary>
/// 关闭数据库连接
/// </summary>
public void Close()
{
if (_conn != null)
{
_comm.Dispose();
_conn.Close();
_conn.Dispose();
}
}
/// <summary>
/// 给sqlite数据库加密
/// </summary>
/// <param name="password">密码</param>
public void Encrypt(string password)
{
try
{
if (_conn != null)
{
_conn.ChangePassword(password);
}
}
catch
{
throw;
}
}
#endregion
#region 查询
/// <summary>
/// 执行sql语句
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
public DataTable ExecuteSQL(string sql)
{
try
{
_comm.Transaction = _trans;
_comm.CommandText = sql;
DataTable dt = new DataTable();
using (SQLiteDataAdapter adapter = new SQLiteDataAdapter(_comm))
{
adapter.Fill(dt);
}
return dt;
}
catch
{
throw;
}
}
#endregion
#region 事务管理
/// <summary>
/// 开始执行事务
/// </summary>
public void BeginTransaction()
{
if (_conn != null)
{
_trans = _conn.BeginTransaction();
}
}
/// <summary>
/// 事务结束,保存并提交数据库数据,
/// </summary>
public void Commit()
{
if (_trans != null)
{
_trans.Commit();
}
}
/// <summary>
/// 回滚事务
/// </summary>
public void Rollback()
{
if (_trans != null)
{
_trans.Rollback();
}
}
/// <summary>
/// 结束事务,并释放资源
/// </summary>
public void EndTransaction()
{
if (_trans != null)
{
_trans.Dispose();
_trans = null;
}
}
#endregion
#endregion
#region IDisposable 成员
public void Dispose()
{
this.Close();
}
#endregion
}
PostgresqlDB.cs
/// <summary>
/// 数据库管理类
/// 直接操作数据库
/// </summary>
public class PostgresqlDB : IDisposable
{
#region 字段
#region 连接配置
/// <summary>
/// 服务器地址
/// </summary>
private string server;
/// <summary>
/// 端口
/// </summary>
private string port;
/// <summary>
/// 用户名
/// </summary>
private string username;
/// <summary>
/// 密码
/// </summary>
private string password;
/// <summary>
/// 数据库名称
/// </summary>
private string db;
#endregion
#region 数据库操作相关变量
/// <summary>
/// 数据库连接器
/// </summary>
private NpgsqlConnection _conn;
/// <summary>
/// 通过连接器创建NpgsqlCommand对象,用于执行SQL语句
/// </summary>
private NpgsqlCommand _comm;
/// <summary>
/// 将数据表中获取的记录生成DataSet
/// </summary>
private NpgsqlDataAdapter _adapter;
/// <summary>
/// 创建一个事务对象
/// </summary>
private NpgsqlTransaction _trans;
#endregion
#endregion
#region 构造函数
private PostgresqlDB() { }
/// <summary>
/// 数据库管理类
/// </summary>
/// <param name="dbConfig">数据库配置</param>
public PostgresqlDB(string server, string port, string username, string password, string db)
{
this.server = server;
this.port = port;
this.username = username;
this.password = password;
this.db = db;
}
~PostgresqlDB()
{
}
#endregion
#region 公共方法
#region 数据库操作:连接数据库、断开数据库、数据库连接状态
/// <summary>
/// 打开数据库连接
/// </summary>
/// <returns></returns>
public bool Open()
{
try
{
//构造SQL语句
string sql = String.Format(
"server={0};port={1};userid={2};password={3};database={4};pooling=true;maxpoolsize=40;timeout=5;",
server, port, username, password, db);
//初始化数据库连接参数
_conn = new NpgsqlConnection(sql);
//打开数据库连接
_conn.Open();
//初始化
_comm = _conn.CreateCommand();
_adapter = new NpgsqlDataAdapter(_comm);
_trans = null;
return true;
}
catch (Exception ex)
{
if (_conn != null)
_conn.Close();
_conn = null;
return false;
}
}
/// <summary>
/// 关闭数据库连接
/// </summary>
public void Close()
{
if (_conn != null)
{
_adapter.Dispose();
_adapter = null;
_comm.Dispose();
_comm = null;
_conn.Close();
_conn.Dispose();
_conn = null;
}
}
/// <summary>
/// 获取数据库的连接状态
/// </summary>
/// <returns>true表示已连接,false表示未连接</returns>
public bool GetConnStatus()
{
return (_conn != null && _conn.State == ConnectionState.Open);
}
#endregion
#region 数据表操作:查询数据表或视图是否存在
/// <summary>
/// 查询指定名称的数据表是否存在
/// </summary>
/// <param name="tableName">数据表名</param>
/// <returns>true:存在,false:不存在</returns>
public bool QueryTableIsExist(string tableName)
{
//构建SQL语句
string sql = String.Format("select count(*) from pg_tables where tablename = '{0}';", tableName.ToLower());
//执行SQL语句
_comm.Transaction = _trans;
_comm.CommandText = sql;
NpgsqlDataReader readerTemp = _comm.ExecuteReader();
//获取查询结果
long value = -1;
if (readerTemp.HasRows == true)
{
readerTemp.Read();
value = readerTemp.GetInt64(0);
}
//释放资源
readerTemp.Close();
//value=1表示数据表存在;value=0表示数据表不存在
if (value > 0)
{
return true;
}
return false;
}
/// <summary>
/// 查询指定名称的视图是否存在
/// </summary>
/// <param name="viewName">视图名</param>
/// <returns>true:存在,false:不存在</returns>
public bool QueryViewIsExist(string viewName)
{
//构建SQL语句
string sql = String.Format("select count(*) from pg_views where viewname = '{0}';", viewName.ToLower());
//执行SQL语句
_comm.Transaction = _trans;
_comm.CommandText = sql;
NpgsqlDataReader readerTemp = _comm.ExecuteReader();
//获取查询结果
long value = -1;
if (readerTemp.HasRows == true)
{
readerTemp.Read();
value = readerTemp.GetInt64(0);
}
//释放资源
readerTemp.Close();
//value=1表示数据表存在;value=0表示数据表不存在
if (value == 0)
{
return false;
}
return true;
}
#endregion
#region 执行sql语句
/// <summary>
/// 执行sql语句
/// </summary>
/// <param name="sql"></param>
public void ExecuteNonQuery(string sql)
{
try
{
_comm.Transaction = _trans;
_comm.CommandText = sql;
_comm.ExecuteNonQuery();
}
catch
{
throw;
}
}
/// <summary>
/// 执行sql语句
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
public DataTable ExecuteQuery(string sql)
{
try
{
_comm.Transaction = _trans;
_comm.CommandText = sql;
DataTable dt = new DataTable();
using (NpgsqlDataAdapter adapter = new NpgsqlDataAdapter(_comm))
{
adapter.Fill(dt);
}
return dt;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region 事务管理
/// <summary>
/// 开始执行事务
/// </summary>
public void BeginTransaction()
{
if (_conn != null)
{
_trans = _conn.BeginTransaction();
}
}
/// <summary>
/// 事务结束,保存并提交数据库数据,
/// </summary>
public void Commit()
{
if (_trans != null)
{
_trans.Commit();
}
}
/// <summary>
/// 回滚事务
/// </summary>
public void Rollback()
{
if (_trans != null)
{
_trans.Rollback();
}
}
/// <summary>
/// 结束事务,并释放资源
/// </summary>
public void EndTransaction()
{
if (_trans != null)
{
_trans.Dispose();
_trans = null;
}
}
#endregion
#endregion
public void Dispose()
{
this.Close();
}
}