|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
using System.Linq;
|
|
|
using System.Runtime.InteropServices;
|
|
|
using System.Threading;
|
|
|
using NeighborInterpolator;
|
|
|
|
|
|
namespace Construction.BatchCreateMap
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 网格化执行上下文,包含各算法执行所需的全部信息。
|
|
|
/// </summary>
|
|
|
public class GridCreateContext
|
|
|
{
|
|
|
public GridCreateParameter Parameter { get; set; }
|
|
|
public string InputFile { get; set; }
|
|
|
public string OutputFile { get; set; }
|
|
|
/// <summary>边界文件路径,无边界时为 "NULL"</summary>
|
|
|
public string OutlineFile { get; set; }
|
|
|
/// <summary>断层文件路径,无断层时为 "NULL"</summary>
|
|
|
public string FaultFile { get; set; }
|
|
|
public string CurveFile { get; set; }
|
|
|
public string DfgFile { get; set; }
|
|
|
public string OutputDir { get; set; }
|
|
|
public string FileName { get; set; }
|
|
|
public int Flag { get; set; }
|
|
|
public ProgressEvent ProgressChanged { get; set; }
|
|
|
public List<int> ProcessIds { get; set; }
|
|
|
public string GridModelExePath { get; set; }
|
|
|
public string CurveModelExePath { get; set; }
|
|
|
/// <summary>
|
|
|
/// 网格化后处理回调。参数为实际使用的断层文件路径(可为 null)。
|
|
|
/// </summary>
|
|
|
public Func<string, bool> RunPostProcessing { get; set; }
|
|
|
public Action<string, string> AppendFile { get; set; }
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 网格化算法策略接口。
|
|
|
/// </summary>
|
|
|
public interface IGridCreator
|
|
|
{
|
|
|
bool Execute(GridCreateContext ctx);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 根据算法类型返回对应的策略实例。
|
|
|
/// </summary>
|
|
|
public static class GridCreatorFactory
|
|
|
{
|
|
|
private static readonly Dictionary<ModelCreateType, IGridCreator> _registry =
|
|
|
new Dictionary<ModelCreateType, IGridCreator>
|
|
|
{
|
|
|
[ModelCreateType.Curvature] = new CurvatureGridCreator(),
|
|
|
[ModelCreateType.IDM] = new IdwGridCreator(),
|
|
|
[ModelCreateType.NatureNeighbor] = new NatureNeighborGridCreator(),
|
|
|
[ModelCreateType.QuikGrid] = new QuikGridCreator(),
|
|
|
[ModelCreateType.GmtSplineGrid] = new GmtSplineGridCreator(),
|
|
|
};
|
|
|
|
|
|
private static readonly IGridCreator _defaultCreator = new MinTensionGridCreator();
|
|
|
|
|
|
public static IGridCreator Get(ModelCreateType type) =>
|
|
|
_registry.TryGetValue(type, out var creator) ? creator : _defaultCreator;
|
|
|
}
|
|
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
// 内部辅助
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
internal static class NativeMethods
|
|
|
{
|
|
|
[DllImport("kernel32.dll")]
|
|
|
internal static extern uint GetCurrentThreadId();
|
|
|
}
|
|
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
// 最小曲率法 —— 调用外部进程 SurfaceGrid.exe
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
internal class CurvatureGridCreator : IGridCreator
|
|
|
{
|
|
|
public bool Execute(GridCreateContext ctx)
|
|
|
{
|
|
|
var para = ctx.Parameter;
|
|
|
|
|
|
var dic = new Dictionary<string, object>
|
|
|
{
|
|
|
{ "--source-point-file", $"\"{ctx.InputFile}\"" },
|
|
|
{ "--fault", $"\"{ctx.FaultFile}\"" },
|
|
|
{ "--breakline", $"\"{ctx.OutlineFile}\"" },
|
|
|
{ "--x-nodes-count", (ulong)para.M },
|
|
|
{ "--max-iteration", -1 },
|
|
|
{ "--residual", 0.0001 },
|
|
|
{ "--fill-value", 0.0 },
|
|
|
{ "--fault-edge-level", 0 },
|
|
|
{ "--output-file", $"\"{ctx.CurveFile}\"" },
|
|
|
{ "--estimate-factor", 0 },
|
|
|
{ "--corner-weight", 64 },
|
|
|
{ "--contour-step", para.CurveSpace },
|
|
|
{ "--contour-mark-step", para.LableSpace },
|
|
|
{ "--insert-times", para.Times },
|
|
|
{ "--smooth-times", para.Smooth },
|
|
|
{ "--area", $"{para.XMin},{para.YMin},{para.XMax},{para.YMax}" },
|
|
|
};
|
|
|
|
|
|
string strParameter = string.Join(" ", dic.Select(x => $"{x.Key} {x.Value}"));
|
|
|
|
|
|
Process p = new Process();
|
|
|
p.StartInfo.FileName = "SurfaceGrid.exe";
|
|
|
p.StartInfo.UseShellExecute = false;
|
|
|
p.StartInfo.RedirectStandardInput = false;
|
|
|
p.StartInfo.RedirectStandardOutput = false;
|
|
|
p.StartInfo.RedirectStandardError = false;
|
|
|
p.StartInfo.CreateNoWindow = true;
|
|
|
p.StartInfo.Arguments = strParameter;
|
|
|
p.Start();
|
|
|
ctx.ProcessIds.Add(p.Id);
|
|
|
p.WaitForExit();
|
|
|
p.Close();
|
|
|
|
|
|
return ctx.RunPostProcessing(ctx.FaultFile);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
// 反距离加权法 —— 在独立线程中调用 ModelCreateIDW
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
internal class IdwGridCreator : IGridCreator
|
|
|
{
|
|
|
public bool Execute(GridCreateContext ctx)
|
|
|
{
|
|
|
var para = ctx.Parameter;
|
|
|
|
|
|
IntPtr pEvent = IntPtr.Zero;
|
|
|
if (ctx.ProgressChanged != null)
|
|
|
{
|
|
|
pEvent = Marshal.GetFunctionPointerForDelegate(ctx.ProgressChanged);
|
|
|
}
|
|
|
|
|
|
bool bResult = false;
|
|
|
LayerCreate.ProcessThread = new Thread(new ThreadStart(() =>
|
|
|
{
|
|
|
LayerCreate.ProcessThreadId = NativeMethods.GetCurrentThreadId();
|
|
|
try
|
|
|
{
|
|
|
ModelCreateIDW.IDWModelCreate(
|
|
|
ctx.InputFile, ctx.OutlineFile, ctx.FaultFile, ctx.CurveFile,
|
|
|
para.M, para.Smooth, 3, pEvent, para.Times, para.CurveSpace, para.LableSpace,
|
|
|
para.XMin, para.YMin, para.XMax, para.YMax);
|
|
|
bResult = ctx.RunPostProcessing(ctx.FaultFile);
|
|
|
}
|
|
|
catch (ThreadAbortException)
|
|
|
{
|
|
|
bResult = false;
|
|
|
}
|
|
|
}), 2621440);
|
|
|
|
|
|
LayerCreate.ProcessThread.Start();
|
|
|
LayerCreate.ProcessThread.Join();
|
|
|
return bResult;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
// 自然临近法 —— 在独立线程中调用 GridCreator
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
internal class NatureNeighborGridCreator : IGridCreator
|
|
|
{
|
|
|
public bool Execute(GridCreateContext ctx)
|
|
|
{
|
|
|
var para = ctx.Parameter;
|
|
|
bool bResult = false;
|
|
|
|
|
|
LayerCreate.ProcessThread = new Thread(new ThreadStart(() =>
|
|
|
{
|
|
|
LayerCreate.ProcessThreadId = NativeMethods.GetCurrentThreadId();
|
|
|
try
|
|
|
{
|
|
|
GridCreator creater = new GridCreator();
|
|
|
creater.Create(
|
|
|
ctx.InputFile, ctx.CurveFile, ctx.OutlineFile,
|
|
|
para.M, para.N, para.Times, para.CurveSpace, para.LableSpace,
|
|
|
para.XMin, para.YMin, para.XMax, para.YMax);
|
|
|
bResult = ctx.RunPostProcessing(ctx.FaultFile);
|
|
|
}
|
|
|
catch (ThreadAbortException)
|
|
|
{
|
|
|
bResult = false;
|
|
|
}
|
|
|
}));
|
|
|
|
|
|
LayerCreate.ProcessThread.Start();
|
|
|
LayerCreate.ProcessThread.Join();
|
|
|
return bResult;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
// 快速网格化 —— 调用 QuikGridCS
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
internal class QuikGridCreator : IGridCreator
|
|
|
{
|
|
|
public bool Execute(GridCreateContext ctx)
|
|
|
{
|
|
|
var para = ctx.Parameter;
|
|
|
return QuikGridCS.Interface.QuikGridCreate(
|
|
|
ctx.InputFile, ctx.CurveFile,
|
|
|
para.M, para.N, para.CurveSpace, para.LableSpace, para.Smooth);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
// 样条插值法 —— 调用外部进程 GmtSurfaceGrid.exe
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
internal class GmtSplineGridCreator : IGridCreator
|
|
|
{
|
|
|
public bool Execute(GridCreateContext ctx)
|
|
|
{
|
|
|
var para = ctx.Parameter;
|
|
|
string strOutputFile = $"{ctx.OutputDir}{ctx.FileName}.grd";
|
|
|
|
|
|
string strParameter = string.Format(
|
|
|
"\"{0}\" \"{1}\" \"{2}\" \"{3}\" \"{4}\" {5} {6} {7} {8} {9} {10} {11} {12}",
|
|
|
ctx.InputFile, strOutputFile, ctx.FaultFile,
|
|
|
ctx.OutlineFile, ctx.CurveFile, para.XStep,
|
|
|
0, para.CurveSpace, para.LableSpace,
|
|
|
para.XMin, para.YMin, para.XMax, para.YMax);
|
|
|
|
|
|
string exeDir = System.IO.Path.GetDirectoryName(
|
|
|
System.Reflection.Assembly.GetExecutingAssembly().Location);
|
|
|
string exeFilePath = System.IO.Path.Combine(exeDir, "GmtSurfaceGrid.exe");
|
|
|
|
|
|
Trace.WriteLine(strParameter);
|
|
|
|
|
|
Process p = new Process();
|
|
|
p.StartInfo.FileName = exeFilePath;
|
|
|
p.StartInfo.UseShellExecute = false;
|
|
|
p.StartInfo.RedirectStandardOutput = true;
|
|
|
p.StartInfo.RedirectStandardError = true;
|
|
|
p.StartInfo.CreateNoWindow = true;
|
|
|
p.StartInfo.Arguments = strParameter;
|
|
|
p.Start();
|
|
|
p.WaitForExit();
|
|
|
string output = p.StandardOutput.ReadToEnd();
|
|
|
string error = p.StandardError.ReadToEnd();
|
|
|
int exitCode = p.ExitCode;
|
|
|
p.Close();
|
|
|
|
|
|
return exitCode == 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
// 最小张力法(默认) —— 依次调用 GridModel.exe 和 CurveModel.exe
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
internal class MinTensionGridCreator : IGridCreator
|
|
|
{
|
|
|
public bool Execute(GridCreateContext ctx)
|
|
|
{
|
|
|
var para = ctx.Parameter;
|
|
|
|
|
|
string strParameter;
|
|
|
if (ctx.OutlineFile.Equals("NULL", StringComparison.CurrentCultureIgnoreCase))
|
|
|
{
|
|
|
strParameter = string.Format(
|
|
|
"\"{0}\" \"{1}\" {2} \"{3}\" \"{4}\" {5} {6} {7} {8} {9} {10} {11}",
|
|
|
ctx.InputFile, ctx.OutputFile, para.Times,
|
|
|
ctx.OutlineFile, ctx.FaultFile,
|
|
|
para.M, para.Smooth, 0,
|
|
|
para.XMin, para.YMin, para.XMax, para.YMax);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
strParameter = string.Format(
|
|
|
"\"{0}\" \"{1}\" {2} \"{3}\" \"{4}\" {5} {6} {7}",
|
|
|
ctx.InputFile, ctx.OutputFile, para.Times,
|
|
|
ctx.OutlineFile, ctx.FaultFile,
|
|
|
para.M, para.Smooth, 0);
|
|
|
}
|
|
|
|
|
|
Trace.WriteLine(strParameter);
|
|
|
|
|
|
Process p = new Process();
|
|
|
p.StartInfo.FileName = ctx.GridModelExePath;
|
|
|
p.StartInfo.UseShellExecute = false;
|
|
|
p.StartInfo.RedirectStandardInput = false;
|
|
|
p.StartInfo.RedirectStandardOutput = false;
|
|
|
p.StartInfo.RedirectStandardError = false;
|
|
|
p.StartInfo.CreateNoWindow = true;
|
|
|
p.StartInfo.Arguments = strParameter;
|
|
|
p.Start();
|
|
|
p.WaitForExit();
|
|
|
p.Close();
|
|
|
|
|
|
if (ctx.Flag >= 3) return true;
|
|
|
|
|
|
// 生成等值线
|
|
|
// 原始逻辑:faultFile 为 "NULL" 时置为 null,后续传入 processAfterGrid
|
|
|
string faultFile = ctx.FaultFile.Equals("NULL") ? null : ctx.FaultFile;
|
|
|
|
|
|
string strCurveParameter = $"\"{ctx.OutputFile}\" \"{ctx.CurveFile}\"";
|
|
|
if (faultFile != null && faultFile.Length > 0)
|
|
|
{
|
|
|
strCurveParameter += $" \"{faultFile}\" {para.CurveSpace}";
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
strCurveParameter += $" NULL {para.CurveSpace}";
|
|
|
}
|
|
|
if (para.LableSpace > 0)
|
|
|
{
|
|
|
strCurveParameter += $" {para.LableSpace}";
|
|
|
}
|
|
|
|
|
|
Trace.WriteLine(strCurveParameter);
|
|
|
|
|
|
p = new Process();
|
|
|
p.StartInfo.FileName = ctx.CurveModelExePath;
|
|
|
p.StartInfo.UseShellExecute = false;
|
|
|
p.StartInfo.RedirectStandardInput = false;
|
|
|
p.StartInfo.RedirectStandardOutput = false;
|
|
|
p.StartInfo.RedirectStandardError = false;
|
|
|
p.StartInfo.CreateNoWindow = true;
|
|
|
p.StartInfo.Arguments = strCurveParameter;
|
|
|
p.Start();
|
|
|
p.WaitForExit();
|
|
|
p.Close();
|
|
|
|
|
|
if (faultFile != null && faultFile.Length > 0)
|
|
|
ctx.AppendFile(ctx.CurveFile, faultFile);
|
|
|
|
|
|
return ctx.RunPostProcessing(faultFile);
|
|
|
}
|
|
|
}
|
|
|
}
|