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 TerraUtils
{
private static string pyFile;
public static int DEFAULT_MAX_LEVEL = 16;
///
/// 获取Python文件
///
public static string PyFile
{
get
{
if (string.IsNullOrWhiteSpace(pyFile))
{
pyFile = Path.Combine(ExportUtil.SourcesPath, "merge.py");
}
return pyFile;
}
}
///
/// QGIS工程
///
public static string Qgz
{
get
{
//return Path.Combine(ExportUtil.SourcesPath, "xyz.qgz");
return "xyz.qgz";
}
}
///
/// bat路径
///
public static string BatPath
{
get
{
return @"C:\Program Files\QGIS 3.16\bin\";
}
}
///
/// 基础bat文件
///
public static string BaseBat
{
get
{
// python-qgis-ltr.bat,qgis_process-qgis-ltr.bat
return @"C:\Program Files\QGIS 3.16\bin\qgis_process-qgis-ltr.bat";
}
}
///
/// 获取发布地址
///
public static string GetReleaseUrl(string dircode)
{
return "http://{host}/LFData/3d/terrain/" + dircode;
}
///
/// 获取地形路径
///
public static string GetTerrainPath(string dircode)
{
return Path.Combine(SGUtils.LFData, "3d\\terrain", dircode);
}
///
/// 生成
///
/// XYZ参数
/// 错误信息
/// 数据发布ID集合
public static List Generate(XYZArgs args, ref string err)
{
string tifFile = null;
try
{
List metas = XYZUtils.SelectMetas(args.ids, "and type in ('tif', 'tiff')");
if (null == metas || metas.Count == 0) return null;
string dirPath = GetTerrainPath(args.dircode);
//if (Directory.Exists(dirPath)) Tools.DelPath(dirPath); // 已存在的,删除
tifFile = Merge(metas, args, ref err);
if (!File.Exists(tifFile)) return null;
string json = Path.Combine(dirPath, "layer.json");
if (File.Exists(json)) File.Delete(json);
//Generate(args, tifFile, ref err);
CreateTerrain(args, tifFile, ref err);
if (!File.Exists(json)) return null;
Complement(args);
List ids = new List();
int pubid = InsertToDB(metas, args);
if (pubid > 0) ids.Add(pubid);
return ids;
}
catch (Exception ex)
{
LogOut.Error(ex.Message + "\r\n" + ex.StackTrace);
err = ex.Message;
return null;
}
/*finally
{
if (!string.IsNullOrEmpty(tifFile) && File.Exists(tifFile)) File.Delete(tifFile);
}*/
}
///
/// 合并
///
public static string Merge(List metas, XYZArgs args, ref string err)
{
string txtFile = null;
try
{
string dirPath = GetTerrainPath(args.dircode);
if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);
txtFile = Path.Combine(Tools.TempDir, ExportUtil.DateStr + ".txt");
string tifFile = Path.Combine(dirPath, args.dircode + ".tif");
int pubid = PubDBHelper.GetPushlishId(args.dircode, "DEM");
if (pubid > 0 && File.Exists(tifFile))
{
List ids = PubDBHelper.GetPublishMetaId(pubid);
List news = new List();
foreach (SysMeta m in metas)
{
if (!ids.Contains(m.id)) news.Add(m);
}
if (0 == news.Count) return tifFile;
string oldTif = Path.Combine(dirPath, args.dircode + "_old.tif");
if (File.Exists(oldTif)) File.Delete(oldTif);
File.Move(tifFile, oldTif);
WriteText(txtFile, news, oldTif);
}
else
{
if (File.Exists(tifFile)) File.Delete(tifFile);
WriteText(txtFile, metas, null);
}
string cmd = string.Format("python \"{0}\" -qgz {1} -file \"{2}\" -out \"{3}\"", PyFile, Qgz, txtFile, tifFile);
err = Tools.ExecCmd(cmd, true, false);
return tifFile;
}
catch (Exception ex)
{
LogOut.Error(ex.Message + "\r\n" + ex.StackTrace);
err = ex.Message;
return null;
}
finally
{
if (!string.IsNullOrEmpty(txtFile) && File.Exists(txtFile)) File.Delete(txtFile);
string dirPath = GetTerrainPath(args.dircode);
string tifFile = Path.Combine(dirPath, args.dircode + ".tif");
string oldTif = Path.Combine(dirPath, args.dircode + "_old.tif");
if (File.Exists(tifFile) && File.Exists(oldTif)) File.Delete(oldTif);
}
}
///
/// 写文本文件
///
private static void WriteText(string txtFile, List list, string tif)
{
string uploadFolder = Tools.GetSetting("uploadFolder");
List files = new List();
if (!string.IsNullOrEmpty(tif)) files.Add(tif);
foreach (SysMeta meta in list)
{
string filePath = Path.Combine(uploadFolder, meta.path);
if (File.Exists(filePath)) files.Add(filePath);
}
string str = string.Join("\r\n", files);
File.WriteAllText(txtFile, str);
}
///
/// 获取地形最大级别
///
private static int GetTerrainMaxLevel(XYZArgs args, string tifFile)
{
string ctbPath = Tools.GetSetting("ctbPath");
string dirPath = GetTerrainPath(args.dircode);
string gdal_data = string.Format("set GDAL_DATA={0}\\data", ctbPath);
string createLayer = string.Format("{0}\\ctb-tile.exe -l -o \"{1}\" -f Mesh \"{2}\\{3}.tif\"", ctbPath, dirPath, dirPath, args.dircode);
Tools.ExecCmd(new List() { gdal_data, createLayer });
string layerJson = Path.Combine(dirPath, "layer.json");
if (!File.Exists(layerJson)) return DEFAULT_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;
}
///
/// 创建高程切片
///
private static void CreateTerrain(XYZArgs args, string tifFile, ref string err)
{
string ctbPath = Tools.GetSetting("ctbPath");
string dirPath = GetTerrainPath(args.dircode);
int maxLevel = GetTerrainMaxLevel(args, tifFile);
string gdal_data = string.Format("set GDAL_DATA={0}\\data", ctbPath);
// -N 顶点法线, -C 强制创建缺失根瓦片, -R 不覆盖现有文件
string createMesh = string.Format("{0}\\ctb-tile.exe -R -C -s {4} -o \"{1}\" -f Mesh \"{2}\\{3}.tif\"", ctbPath, dirPath, dirPath, args.dircode, maxLevel);
string createLayer = string.Format("{0}\\ctb-tile.exe -l -s {4} -o \"{1}\" -f Mesh \"{2}\\{3}.tif\"", ctbPath, dirPath, dirPath, args.dircode, maxLevel);
List list = new List() { gdal_data, createMesh, createLayer };
err = Tools.ExecCmd(list);
}
///
/// 补充文件
///
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);
}
///
/// 插入数据库
///
private static int InsertToDB(List metas, XYZArgs args)
{
//if (PubDBHelper.IsPublish(args.dircode, "DEM")) return 1;
int pubid = PubDBHelper.GetPushlishId(args.dircode, "DEM");
if (pubid > 0) // 更新发布
{
List 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;
}
///
/// 获取中心点
///
private static string GetPointZ(XYZArgs args)
{
string dirPath = GetTerrainPath(args.dircode);
string txtFile = Path.Combine(dirPath, args.dircode + "_cs.txt");
if (!File.Exists(txtFile)) return null;
string[] strs = File.ReadAllLines(txtFile, Encoding.UTF8);
// File.Delete(txtFile); // 删除坐标文件
if (null == strs || strs.Length == 0) return null;
string[] str = strs[0].Split(new string[] { ", " }, StringSplitOptions.None);
int i = 18;
for (; i > -1; i--)
{
string path = Path.Combine(dirPath, i.ToString());
if (Directory.Exists(path))
{
break;
}
}
return string.Format("ST_GeomFromText('POINT Z ({0} {1} {2})')", str[1], str[0], i);
}
/*///
/// 生成高程切片 *
///
private static void Generate(XYZArgs args, string tifFile, ref string err)
{
string dirPath = GetTerrainPath(args.dircode).Replace("\\", "/");
string name = "ctb_" + ExportUtil.DateStr;
string runDocker = string.Format("docker run -id --name {0} -v \"{1}\":\"/data\" tumgis/ctb-quantized-mesh", name, dirPath);
string createMesh = string.Format("docker exec {0} ctb-tile -f Mesh -C -N -s {1} -e {2} -o /data /data/{3}.tif", name, args.max, args.min, args.dircode); // Mesh, Terrain
string createLayer = string.Format("docker exec {0} ctb-tile -f Mesh -C -N -s {1} -e {2} -l -o /data /data/{3}.tif", name, args.max, args.min, args.dircode); // Mesh, Terrain
string stop = string.Format("docker stop {0}", name);
string rm = string.Format("docker rm {0}", name);
List list = new List { runDocker, createMesh, createLayer, stop, rm };
err = Tools.ExecCmd(list);
}*/
}
}