You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

365 lines
13 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OpenAuth.App.Request;
using OpenAuth.App.Response;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenAuth.App.BasicQueryService
{
public class CommonDataManager
{
ISqlSugarClient client;
public CommonDataManager(ISqlSugarClient client)
{
this.client = client;
}
/// <summary>
/// wkt转geom数据
/// </summary>
/// <param name="wkt"></param>
/// <param name="wkid"></param>
/// <returns></returns>
public string WktToGeometry(string wkt, int wkid)
{
StringBuilder geomsql = new StringBuilder();
geomsql.AppendFormat(" SELECT CAST(st_geomfromtext('{0}',{1}) AS text) geom", wkt, wkid);
var model_geom = client.SqlQueryable<dynamic>(geomsql.ToString()).First();
return model_geom.geom;
}
/// <summary>
/// Pgsql获取GeoJson数据
/// </summary>
/// <param name="req"></param>
/// <param name="_configuration"></param>
/// <returns></returns>
public JToken PgsqlGeoJsonCommon(QueryGeoJsonCommonReq req)
{
//如果有的参数为空,设置参数的默认值
req.init();
//查询列的数据
StringBuilder sqlColumn = new StringBuilder();
sqlColumn.AppendFormat(" select {1} from {0} {3} order by \"{2}\"", req.tablename, req.column, req.order,
req.where);
StringBuilder sqlGeo = new StringBuilder();
sqlGeo.AppendFormat(" select st_asgeojson(\"{0}\") geom from \"{1}\" {3} order by \"{2}\"", req.geom,
req.tablename, req.order, req.where);
return PgsqlGeoJsonCommon(sqlColumn, sqlGeo, req.pageIndex, req.limit);
}
/// <summary>
/// 查询GeoJson公共方法
/// </summary>
/// <param name="sqlColumn"></param>
/// <param name="sqlGeom"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="_configuration"></param>
/// <returns></returns>
public JToken PgsqlGeoJsonCommon(StringBuilder sqlColumn, StringBuilder sqlGeom, int pageIndex, int pageSize)
{
//获取到数据库操作实例
int total = 0;
int totalPage = 0;
//查询列
var dt_properties = client.SqlQueryable<dynamic>(sqlColumn.ToString())
.ToPageList(pageIndex, pageSize, ref total, ref totalPage);
//列数据转换为字符串
string str_properties = JsonConvert.SerializeObject(dt_properties);
//列数据转换为json对象
JToken jtoken_properties = (JToken)JsonConvert.DeserializeObject(str_properties);
//查询geojson数据
var dt_geom = client.SqlQueryable<dynamic>(sqlGeom.ToString()).ToDataTablePage(pageIndex, pageSize);
//组装最终数据
JObject obj = new JObject();
JArray array = new JArray();
obj.Add("type", "FeatureCollection");
obj.Add("totalNumber", total);
obj.Add("totalPage", totalPage);
//遍历geojson数据
for (var i = 0; i < dt_geom.Rows.Count; i++)
{
//行数据
DataRow item = dt_geom.Rows[i];
//单条geojson
string _geom = item["geom"] == DBNull.Value ? "" : item["geom"].ToString();
//给数据赋值
JObject featureObj = new JObject();
featureObj.Add("type", "Feature");
featureObj.Add("geometry", (JToken)JsonConvert.DeserializeObject(_geom));
featureObj.Add("properties", jtoken_properties[i]);
//添加到数组
array.Add(featureObj);
}
obj.Add("features", array);
return obj;
}
/// <summary>
/// 获取列名
/// </summary>
/// <param name="tablename"></param>
/// <returns></returns>
public List<dynamic> SearchColumnsList(string tablename)
{
//查询列名和注释描述
StringBuilder columnSql = new StringBuilder();
columnSql.AppendFormat(
@$" SELECT a.attname column_name,col_description(a.attrelid,a.attnum) as description,format_type(a.atttypid,a.atttypmod) as column_type
FROM pg_class as c,pg_attribute as a
where c.relname = '{tablename}'
and a.attrelid = c.oid
and a.attnum>0
and attstattarget = -1");
//查询结果
var column_list = client.SqlQueryable<dynamic>(columnSql.ToString()).ToList();
return column_list;
}
/// <summary>
/// 矢量切片公共方法
/// </summary>
/// <param name="req"></param>
/// <param name="_configuration"></param>
/// <returns></returns>
public byte[] VectorTile(VectorTileSearchModel req)
{
req.Init();
List<double> lons = getLon(req.x, req.z);
List<double> lats = getLat(req.y, req.z);
double lonmin = lons[0];
double lonmax = lons[1];
double latmin = lats[1];
double latmax = lats[0];
StringBuilder sql = new StringBuilder();
sql.AppendFormat(
$" SELECT ST_AsMVT(tile, '{req.source_layer}', 4096, 'geom') tile FROM (SELECT {req.field}ST_AsMVTGeom(geom, ST_Transform(ST_MakeEnvelope({lonmin},{latmin},{lonmax},{latmax}, 4326),4326),4096, 256, true) AS geom FROM public.{req.table} where {req.filter} ) AS tile");
var dataTable = client.Ado.GetDataTable(sql.ToString());
byte[] result = (Byte[])dataTable.Rows[0]["tile"];
return result;
}
/// <summary>
/// 查询最新的主键
/// </summary>
/// <param name="_columm"></param>
/// <param name="tablename"></param>
/// <param name="_gid_const"></param>
/// <returns></returns>
public string GetMaxKeyVal(string _column, string tablename, int _gid_const)
{
string _val = "";
//查询最大的gid
var column_list = SearchColumnsList(tablename);
string _type = column_list[0].column_type;
if (_type != "integer")
{
_val = Guid.NewGuid().ToString();
return _val;
}
var _maxgid = client
.SqlQueryable<dynamic>(
$"SELECT max(\"{_column}\") \"maxGid\" FROM \"{tablename}\" where \"{_column}\" < 6000000").First()
.maxGid;
//gid为空时说明一条数据都没有
if (_maxgid == null)
_val = _gid_const.ToString();
else
{
//如果大于设定值,在此基础上加一,否则设置为默认值
if (_maxgid >= _gid_const)
_val = (_maxgid + 1).ToString();
else
_val = _gid_const.ToString();
}
return _val;
}
/// <summary>
/// 格式化wkt数据兼容多个地块
/// </summary>
/// <param name="_wkt"></param>
/// <param name="_newType"></param>
/// <param name="_len"></param>
/// <returns></returns>
public string WktDataConvert(string _wkt, string _newType, int _len)
{
//使用逗号分割
var list = _wkt.Split(",");
//返回值
StringBuilder res = new StringBuilder();
//扩展的维度,用 0补齐
string extStr = "";
for (int i = 0; i < list.Length; i++)
{
//当前项
var item = list[i];
extStr = GetWktDemension(item, _len);
if (i == 0)
{
//第一项数据先去除前缀
item = item.Substring(item.IndexOf("(")).TrimStart('(');
if (_newType == "MULTIPOLYGON ZM")
item = "(((" + item;
else if (_newType == "MULTILINESTRING")
item = "((" + item;
//扩展后的值
item = _newType + item + extStr;
}
else if (i == list.Length - 1)
{
//最后一项
item = item.TrimEnd(')');
if (_newType == "MULTIPOLYGON ZM")
item = item + extStr + ")))";
else if (_newType == "MULTILINESTRING")
item = item + extStr + "))";
}
else
{
//判断是否存在右括号
if (item.IndexOf(")") > -1)
{
//在第一个右括号前插入维度数据
item = item.Insert(item.IndexOf(")"), extStr);
}
else
{
//在后面追加维度数据
item = item + extStr;
}
}
//追加数据
res.Append($"{item},");
}
string strRes = res.ToString();
//把最后一个逗号截取掉
return strRes.Substring(0, strRes.Length - 1);
}
private string GetWktDemension(string item, int _len)
{
if (item.IndexOf("(") > -1)
{
item = item.Substring(item.IndexOf("("));
item = item.TrimStart('(');
}
string extStr = "";
//数据的维度
var _count = _len - item.Split(" ", StringSplitOptions.RemoveEmptyEntries).Length;
//扩展维度
if (_count == 1)
extStr = " 0";
else if (_count == 2)
extStr = " 0 0";
return extStr;
}
#region Util
/// <summary>
/// 瓦片转经度
/// </summary>
/// <param name="x">列号</param>
/// <param name="z">缩放级别</param>
/// <returns></returns>
public static double tile2lon(int x, int z)
{
return x / Math.Pow(2.0, z) * 360.0 - 180;
}
/// <summary>
/// 瓦片转纬度
/// </summary>
/// <param name="y">行号</param>
/// <param name="z">缩放级别</param>
/// <returns></returns>
public static double tile2lat(int y, int z)
{
double n = Math.PI - (2.0 * Math.PI * y) / Math.Pow(2.0, z);
return Math.Atan(Math.Sinh(n)) * 180 / Math.PI;
}
/// <summary>
/// 获取经度最大值和经度最小值
/// </summary>
/// <param name="x">列号</param>
/// <param name="z">缩放级别</param>
/// <returns></returns>
public static List<double> getLon(int x, int z)
{
List<double> lonExtent = new List<double>();
lonExtent.Add(tile2lon(x, z));
lonExtent.Add(tile2lon(x + 1, z));
return lonExtent;
}
/// <summary>
/// 获取纬度最大值和经度最小值
/// </summary>
/// <param name="y">列号</param>
/// <param name="z">缩放级别</param>
/// <returns></returns>
public static List<double> getLat(int y, int z)
{
List<double> latExtent = new List<double>();
latExtent.Add(tile2lat(y, z));
latExtent.Add(tile2lat(y + 1, z));
return latExtent;
}
#endregion
public byte[] VectorTile1(VectorTileSearchModel req)
{
req.Init();
List<double> lons = getLon(req.x, req.z);
List<double> lats = getLat(req.y, req.z);
double lonmin = lons[0];
double lonmax = lons[1];
double latmin = lats[1];
double latmax = lats[0];
StringBuilder sql = new StringBuilder();
sql.AppendFormat(
$" SELECT ST_AsMVT(tile, '{req.source_layer}', 4096, 'geom') tile FROM (SELECT {req.field}ST_AsMVTGeom(geometry, ST_Transform(ST_MakeEnvelope({lonmin},{latmin},{lonmax},{latmax}, 4326),4326),4096, 256, true) AS geom FROM public.{req.table} where {req.filter} ) AS tile");
var dataTable = client.Ado.GetDataTable(sql.ToString());
byte[] result = (Byte[])dataTable.Rows[0]["tile"];
return result;
}
}
}