using ExportMap.db;
|
using ExportMap.Models;
|
using System;
|
using System.Collections.Generic;
|
using System.IO;
|
using System.Linq;
|
using System.Text;
|
using System.Web;
|
|
namespace ExportMap.cs
|
{
|
public class TerrainUtils
|
{
|
private static int terrainMaxLevel = 0;
|
|
private const string EPSG4326 = "EPSG:4326";
|
|
/// <summary>
|
/// 地形最大级别
|
/// </summary>
|
public static int TERRAIN_MAX_LEVEL
|
{
|
get
|
{
|
if (0 == terrainMaxLevel)
|
{
|
string str = Tools.GetSetting("terrainMaxLevel");
|
if (!int.TryParse(str, out terrainMaxLevel))
|
{
|
terrainMaxLevel = 14;
|
}
|
}
|
|
return terrainMaxLevel;
|
}
|
}
|
|
/// <summary>
|
/// 默认最大文件大小:5GB
|
/// </summary>
|
public static long DEFAULT_MAX_SIZE = 5L * 1024 * 1024 * 1024;
|
|
/// <summary>
|
/// 获取发布地址
|
/// </summary>
|
public static string GetReleaseUrl(string dircode)
|
{
|
return "http://{host}/LFData/3d/terrain/" + dircode;
|
}
|
|
/// <summary>
|
/// 获取地形路径
|
/// </summary>
|
public static string GetTerrainPath(string dircode)
|
{
|
return Path.Combine(SGUtils.LFData, "3d\\terrain", dircode);
|
}
|
|
/// <summary>
|
/// 生成
|
/// </summary>
|
/// <param name="args">XYZ参数</param>
|
/// <param name="err">错误信息</param>
|
/// <returns>数据发布ID集合</returns>
|
public static List<int> Generate(XYZArgs args, ref string err)
|
{
|
try
|
{
|
List<SysMeta> metas = XYZUtils.SelectMetas(args.ids, "and type in ('tif', 'tiff', 'dem')");
|
if (null == metas || metas.Count == 0) return PrintInfo("找不到元数据");
|
|
string dirPath = GetTerrainPath(args.dircode);
|
//if (Directory.Exists(dirPath)) Tools.DelPath(dirPath); // 已存在的,删除
|
if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);
|
string subPath = Path.Combine(dirPath, "subs");
|
if (!Directory.Exists(subPath)) Directory.CreateDirectory(subPath);
|
|
int pubid = PubDBHelper.GetPushlishId(args.dircode, "DEM");
|
List<int> metsIds = PubDBHelper.GetPublishMetaId(pubid);
|
|
List<string> files = new List<string>();
|
string uploadFolder = Tools.GetSetting("uploadFolder");
|
foreach (SysMeta meta in metas)
|
{
|
if (metsIds.Contains(meta.id))
|
{
|
PrintInfo("元数据[" + meta.id + "] 已发布。");
|
continue;
|
}
|
string sourceFile = Path.Combine(uploadFolder, meta.path);
|
if (!File.Exists(sourceFile))
|
{
|
PrintInfo("元数据[" + meta.id + "] 不存在。");
|
continue;
|
}
|
|
string targetFile = Path.Combine(subPath, meta.name);
|
ConvertRaster(sourceFile, targetFile);
|
if (File.Exists(targetFile))
|
{
|
files.Add(targetFile);
|
CreateTerrain(args, targetFile, ref err);
|
}
|
}
|
|
CreateLayerJson(args, files, ref err);
|
string json = Path.Combine(dirPath, "layer.json");
|
if (!File.Exists(json)) return PrintInfo("找不到layer.json文件");
|
|
Complement(args);
|
pubid = InsertToDB(metas, args);
|
|
return new List<int> { pubid };
|
}
|
catch (Exception ex)
|
{
|
LogOut.Error(ex.Message + "\r\n" + ex.StackTrace);
|
err = ex.Message;
|
return null;
|
}
|
}
|
|
/// <summary>
|
/// 打印信息
|
/// </summary>
|
private static List<int> PrintInfo(string info)
|
{
|
LogOut.Info("TerrainUtils:" + info);
|
return null;
|
}
|
|
/// <summary>
|
/// 转换栅格文件
|
/// </summary>
|
private static void ConvertRaster(string sourceFile, string targetFile)
|
{
|
if (File.Exists(targetFile)) return;
|
|
string epsg = Tools.GetEPSG(sourceFile);
|
if (epsg == EPSG4326)
|
{
|
File.Copy(sourceFile, targetFile);
|
return;
|
}
|
|
Reproject(sourceFile, targetFile, epsg, EPSG4326);
|
}
|
|
/// <summary>
|
/// 创建高程切片
|
/// </summary>
|
private static void CreateTerrain(XYZArgs args, string tifFile, ref string err)
|
{
|
string ctbPath = Tools.GetSetting("ctbJL");
|
string dirPath = GetTerrainPath(args.dircode);
|
//int maxLevel = GetTerrainMaxLevel(args, tifFile);
|
|
string gdal_data = string.Format("set GDAL_DATA={0}\\data", ctbPath);
|
// -N 顶点法线, -C 强制创建缺失根瓦片, -R 不覆盖现有文件,-f Mesh
|
string createMesh = string.Format("{0}\\ctb-tile.exe -s {1} -o \"{2}\" \"{3}\"", ctbPath, TERRAIN_MAX_LEVEL, dirPath, tifFile);
|
|
List<string> list = new List<string>() { gdal_data, createMesh };
|
SysTask task = TaskDBHelper.CreateTask(args, "DEM", "高程数据(DEM)");
|
err = Tools.ExecCmd(task, list);
|
}
|
|
/// <summary>
|
/// 创建layer.json
|
/// </summary>
|
private static string CreateLayerJson(XYZArgs args, List<string> files, ref string err)
|
{
|
string dirPath = GetTerrainPath(args.dircode);
|
string vrt = Path.Combine(dirPath, "subs", "dem.vrt");
|
CreateVrt(files, vrt);
|
if (!File.Exists(vrt)) return null;
|
|
string ctbPath = Tools.GetSetting("ctbJL");
|
string gdal_data = string.Format("set GDAL_DATA={0}\\data", ctbPath);
|
string createLayer = string.Format("{0}\\ctb-tile.exe -l -s {1} -o \"{2}\" \"{3}\"", ctbPath, TERRAIN_MAX_LEVEL, dirPath, vrt);
|
Tools.ExecCmd(new List<string>() { gdal_data, createLayer });
|
|
return vrt;
|
}
|
|
/// <summary>
|
/// 创建VRT
|
/// </summary>
|
private static void CreateVrt(List<string> files, string vrt)
|
{
|
string str = string.Join("\r\n", files);
|
string filelist = vrt.Replace("dem.vrt", "list.txt");
|
File.WriteAllText(filelist, str);
|
|
string gdalPath = Tools.GetSetting("gdalPath");
|
string cmd = string.Format("\"{0}\\gdalbuildvrt.exe\" -input_file_list \"{1}\" \"{2}\" -overwrite", gdalPath, filelist, vrt);
|
Tools.ExecCmd(new List<string> { cmd });
|
}
|
|
/// <summary>
|
/// 获取地形最大级别
|
/// </summary>
|
private static int GetTerrainMaxLevel(XYZArgs args, string tifFile)
|
{
|
FileInfo fi = new FileInfo(tifFile);
|
if (fi.Length > DEFAULT_MAX_SIZE) return TERRAIN_MAX_LEVEL;
|
|
string ctbPath = Tools.GetSetting("ctbJL");
|
string dirPath = GetTerrainPath(args.dircode);
|
string subPath = Path.Combine(dirPath, "subs");
|
|
string gdal_data = string.Format("set GDAL_DATA={0}\\data", ctbPath);
|
string createLayer = string.Format("{0}\\ctb-tile.exe -l -o \"{1}\" \"{2}\"", ctbPath, subPath, tifFile);
|
|
Tools.ExecCmd(new List<string>() { gdal_data, createLayer });
|
|
string layerJson = Path.Combine(subPath, "layer.json");
|
if (!File.Exists(layerJson)) return TERRAIN_MAX_LEVEL;
|
|
string[] lines = File.ReadAllLines(layerJson, Encoding.UTF8);
|
|
int level = -1;
|
foreach (string line in lines)
|
{
|
if (line.IndexOf("startX") > -1) level++;
|
}
|
if (File.Exists(layerJson)) File.Delete(layerJson);
|
|
return level > TERRAIN_MAX_LEVEL ? TERRAIN_MAX_LEVEL : level;
|
}
|
|
/// <summary>
|
/// 补充文件
|
/// </summary>
|
private static void Complement(XYZArgs args)
|
{
|
string dirPath = GetTerrainPath(args.dircode);
|
string p_0_0 = Path.Combine(dirPath, "0", "0");
|
if (!Directory.Exists(p_0_0)) Directory.CreateDirectory(p_0_0);
|
|
string p_0_1 = Path.Combine(dirPath, "0", "1");
|
if (!Directory.Exists(p_0_1)) Directory.CreateDirectory(p_0_1);
|
|
string s_0_0_0 = Path.Combine(SGUtils.LFData, "dem", "0", "0", "0.terrain");
|
string d_0_0_0 = Path.Combine(dirPath, "0", "0", "0.terrain");
|
if (!File.Exists(d_0_0_0)) File.Copy(s_0_0_0, d_0_0_0, true);
|
|
string s_0_1_0 = Path.Combine(SGUtils.LFData, "dem", "0", "1", "0.terrain");
|
string d_0_1_0 = Path.Combine(dirPath, "0", "1", "0.terrain");
|
if (!File.Exists(d_0_1_0)) File.Copy(s_0_1_0, d_0_1_0, true);
|
|
string layerJson = Path.Combine(dirPath, "layer.json");
|
string[] lines = File.ReadAllLines(layerJson, Encoding.UTF8);
|
//lines[12] = " [ { \"startX\": 0, \"startY\": 0, \"endX\": 1, \"endY\": 0 } ]";
|
for (int i = 0, c = lines.Length; i < c; i++)
|
{
|
if (lines[i].IndexOf("startX") > -1)
|
{
|
lines[i] = " [ { \"startX\": 0, \"startY\": 0, \"endX\": 1, \"endY\": 0 } ]";
|
break;
|
}
|
}
|
|
File.WriteAllLines(layerJson, lines, Encoding.UTF8);
|
}
|
|
/// <summary>
|
/// 插入数据库
|
/// </summary>
|
private static int InsertToDB(List<SysMeta> metas, XYZArgs args)
|
{
|
//if (PubDBHelper.IsPublish(args.dircode, "DEM")) return 1;
|
int pubid = PubDBHelper.GetPushlishId(args.dircode, "DEM");
|
if (pubid > 0) // 更新发布
|
{
|
List<int> ids = PubDBHelper.GetPublishMetaId(pubid);
|
foreach (SysMeta m in metas)
|
{
|
if (!ids.Contains(m.id)) PubDBHelper.InsertMetaPub(m.id, pubid, args.userId);
|
}
|
string geom = GetPointZ(args);
|
PubDBHelper.UpdatePublish(pubid, args.name, args.userId, geom);
|
|
return pubid;
|
}
|
|
SysMeta meta = metas[0];
|
meta.type = "DEM";
|
meta.name = args.name;
|
meta.dircode = args.dircode;
|
|
SysPublish sys = Tools.NewPublish(meta, args, GetReleaseUrl(args.dircode), "3d\\terrain\\" + args.dircode);
|
sys.geom = GetPointZ(args);
|
|
pubid = PubDBHelper.InsertPublish(sys);
|
if (pubid > 0)
|
{
|
sys.id = pubid;
|
PubDBHelper.InsertLayer(sys, new SysMeta()
|
{
|
name = args.name,
|
type = meta.type,
|
dirname = meta.dirname
|
});
|
foreach (SysMeta m in metas)
|
{
|
PubDBHelper.InsertMetaPub(m.id, pubid, args.userId);
|
}
|
}
|
|
return pubid;
|
}
|
|
/// <summary>
|
/// 获取中心点
|
/// </summary>
|
public static string GetPointZ(XYZArgs args)
|
{
|
string dirPath = GetTerrainPath(args.dircode);
|
string vrt = Path.Combine(dirPath, "subs", "dem.vrt");
|
if (!File.Exists(vrt)) return null;
|
|
string gdalPath = Tools.GetSetting("gdalPath");
|
string cmd = string.Format("\"{0}\\gdalinfo.exe\" \"{1}\"", gdalPath, vrt);
|
|
string rs = null;
|
Tools.ExecCmd(new List<string> { cmd }, ref rs);
|
string center = GetCenter(rs);
|
if (string.IsNullOrEmpty(rs)) return null;
|
|
string[] strs = center.Split(new string[] { "," }, StringSplitOptions.None);
|
double x = double.Parse(strs[0]);
|
double y = double.Parse(strs[1]);
|
|
return string.Format("ST_GeomFromText('POINT Z ({0} {1} {2})')", x, y, 12);
|
}
|
|
/// <summary>
|
/// 获取中心坐标
|
/// </summary>
|
private static string GetCenter(string rs)
|
{
|
if (string.IsNullOrEmpty(rs)) return null;
|
|
string[] strs = rs.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
foreach (string str in strs)
|
{
|
if (str.StartsWith("Center "))
|
{
|
int start = str.IndexOf("(");
|
int end = str.IndexOf(")");
|
|
return str.Substring(start + 1, end - start - 1).Replace(" ", "");
|
}
|
}
|
|
return null;
|
}
|
|
/// <summary>
|
/// 重投影
|
/// </summary>
|
public static void Reproject(string sourceFile, string targetFile, string sourceSrs, string targetSrs)
|
{
|
string gdalPath = Tools.GetSetting("gdalPath");
|
string cmd = string.Format("\"{0}\\gdalwarp.exe\" -s_srs {1} -t_srs {2} -r near -of GTiff \"{3}\" \"{4}\"", gdalPath, sourceSrs, targetSrs, sourceFile, targetFile);
|
|
Tools.ExecCmd(new List<string> { cmd });
|
}
|
|
/// <summary>
|
/// 指定投影 *
|
/// </summary>
|
public static void Project(string sourceFile, string targetSrs)
|
{
|
List<string> list = new List<string>();
|
list.Add("cd \"C:\\Program Files\\QGIS 3.16\\apps\\Python37\"");
|
//list.Add("set GDAL_DATA=\"C:\\Program Files\\QGIS 3.16\\share\\gdal\"");
|
//list.Add("set PROJ_LIB=\"C:\\Program Files\\QGIS 3.16\\share\\proj\"");
|
list.Add("\"C:\\Program Files\\QGIS 3.16\\bin\\qgis_process-qgis-ltr.bat\"");
|
|
string cmd = string.Format("python \"C:\\Program Files\\QGIS 3.16\\apps\\Python37\\Scripts\\gdal_edit.py\" -a_srs {0} {1}", targetSrs, sourceFile);
|
list.Add(cmd);
|
|
string rs = "";
|
string err = Tools.ExecCmd(new List<string> { cmd }, ref rs);
|
}
|
}
|
}
|