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; } /// /// wkt转geom数据 /// /// /// /// 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(geomsql.ToString()).First(); return model_geom.geom; } /// /// Pgsql获取GeoJson数据 /// /// /// /// 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); } /// /// 查询GeoJson公共方法 /// /// /// /// /// /// /// public JToken PgsqlGeoJsonCommon(StringBuilder sqlColumn, StringBuilder sqlGeom, int pageIndex, int pageSize) { //获取到数据库操作实例 int total = 0; int totalPage = 0; //查询列 var dt_properties = client.SqlQueryable(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(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; } /// /// 获取列名 /// /// /// public List 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(columnSql.ToString()).ToList(); return column_list; } /// /// 矢量切片公共方法 /// /// /// /// public byte[] VectorTile(VectorTileSearchModel req) { req.Init(); List lons = getLon(req.x, req.z); List 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; } /// /// 查询最新的主键 /// /// /// /// /// 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( $"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; } /// /// 格式化wkt数据,兼容多个地块 /// /// /// /// /// 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 /// /// 瓦片转经度 /// /// 列号 /// 缩放级别 /// public static double tile2lon(int x, int z) { return x / Math.Pow(2.0, z) * 360.0 - 180; } /// /// 瓦片转纬度 /// /// 行号 /// 缩放级别 /// 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; } /// /// 获取经度最大值和经度最小值 /// /// 列号 /// 缩放级别 /// public static List getLon(int x, int z) { List lonExtent = new List(); lonExtent.Add(tile2lon(x, z)); lonExtent.Add(tile2lon(x + 1, z)); return lonExtent; } /// /// 获取纬度最大值和经度最小值 /// /// 列号 /// 缩放级别 /// public static List getLat(int y, int z) { List latExtent = new List(); latExtent.Add(tile2lat(y, z)); latExtent.Add(tile2lat(y + 1, z)); return latExtent; } #endregion public byte[] VectorTile1(VectorTileSearchModel req) { req.Init(); List lons = getLon(req.x, req.z); List 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; } } }