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.
kev/Drawer/SmartNest/SmartWells/CaculateHelpWeb.cs

1130 lines
42 KiB
C#

using Clipper2Lib;
//using ClipperLib;
using DeepNestLib;
using GeoSigma.SigmaDrawerStyle;
using GeoSigmaDrawLib;
using SigmaDrawerElement;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Clipper = Clipper2Lib.Clipper;
namespace SmartWells
{
// public delegate void IterateEventHandler(List<SheetPlacement> placements, double materialUtilization, long elapsedMilliseconds);
// public delegate void ExportPlaceMentsEventHandler(Bitmap bmp, string info);
public class CaculateHelpWeb : IDisposable
{
/// <summary>
/// 任务唯一标识符
/// </summary>
public string TaskId { get; private set; } = Guid.NewGuid().ToString();
public IterateEventHandler IterateEvent { get; set; } = null;
public ExportPlaceMentsEventHandler ExportPlaceMentsEvent { get; set; } = null;
/// <summary>
/// web停止线程任务用
/// </summary>
private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
private CountdownEvent countdown = new CountdownEvent(0);
/// <summary>
/// 部署文件
/// </summary>
public string DeployFile { get; set; } = string.Empty;
/// <summary>
/// 边界图层
/// </summary>
public string BorderLayer { get; set; } = string.Empty;
/// <summary>
/// 断层图层
/// </summary>
public string FaultLayer { get; set; } = string.Empty;
/// <summary>
/// CoverageRate覆盖率
/// </summary>
public double CoverageRate { get; set; } = 0.0;
/// <summary>
/// 单侧井
/// </summary>
public int SingleWell { get; set; } = 0;
/// <summary>
/// 双侧井
/// </summary>
public int DoubleWell { get; set; } = 0;
/// <summary>
/// 消息Id,和前端进度条通讯用
/// </summary>
public string ConnectionId { get; set; } = string.Empty;
/// <summary>
/// 是否已经停止运算
/// </summary>
public bool IsStop { get; set; } = true;
/// <summary>
/// 井参数
/// </summary>
public WellsConfig WellParameters { get; set; } = new WellsConfig();
/// <summary>
/// 计算参数
/// </summary>
public CaculateConfig CaculateParameter { get; set; } = new CaculateConfig();
/// <summary>
/// 显示进度事件
/// </summary>
public Action<float> DisplayProgressAction { get; set; }
public CaculateStatus Status { get; set; } = CaculateStatus.None;
public bool NeedStop
{
get
{
if (nest != null)
{
return nest.NeedStop;
}
return false;
}
set
{
if (nest != null)
{
nest.NeedStop = value;
}
}
}
/// <summary>
/// 图片导出的宽度
/// </summary>
public int ImageWidth { get; set; } = 500;
/// <summary>
/// 图片输出的高度
/// </summary>
public int ImageHeight { get; set; } = 400;
private SvgNestConfig nestConfig;
private double partSpacing = 200;
private double faultInflate = 10;
private double originX = 0;
private double originY = 0;
public NestingContext nest;
WellGroupParameter groupParaSide2;
WellGroupParameter groupParaSide1;
LocalContour wellBox2;
LocalContour wellBox1;
ManualResetEvent ma = new ManualResetEvent(false);
public DrawerData drawer;
public DrawerData OpenDrawerFile()
{
if (!File.Exists(this.DeployFile))
{
return null;
}
if (drawer != null)
{
drawer.Dispose();
drawer = null;
}
drawer = new DrawerData();
//drawer.OpenWithDraw = true;
try
{
if (drawer.OpenFile(this.DeployFile) == false)
{
drawer.Dispose();
drawer = null;
}
}
catch (Exception ex)
{
drawer.Dispose();
drawer = null;
return null;
}
return drawer;
}
/// <summary>
/// 保存指定文件
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public bool SaveDrawerDataFile(string filePath)
{
if (drawer == null) return false;
drawer.SaveAs(filePath);
return File.Exists(filePath);
}
public CaculateHelpWeb()
{
this.nestConfig = new SvgNestConfig();
}
~CaculateHelpWeb()
{
Dispose(false);
}
private bool disposed = false; // 跟踪是否已释放
/// <summary>
/// 受保护的虚方法,用于释放资源
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// 释放托管资源
Console.WriteLine("Releasing managed resources.");
}
// 释放未托管资源
if (drawer != null)
{
drawer.Dispose();
drawer = null;
}
if(this.ma!=null)
{
ma.Dispose();
}
disposed = true;
}
}
/// <summary>
/// 实现 IDisposable 接口
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // 防止垃圾回收器再次调用析构函数
}
/// <summary>
/// 暂停
/// </summary>
public void Pause()
{
NeedStop = true;
Status = CaculateStatus.Pausing;
// 信号关闭阻,塞当前线程
ma.Reset();
}
/// <summary>
/// 继续
/// </summary>
public void Continue()
{
NeedStop = false;
if (this.Status!= CaculateStatus.Pausing
&& this.Status != CaculateStatus.Paused)
{
return;
}
Status = CaculateStatus.Working;
// 信号打开,不阻塞当前线程
ma.Set();
}
/// <summary>
/// 停止
/// </summary>
public void Stop()
{
NeedStop = true;
Status = CaculateStatus.Stopping;
this.IsStop = true;
ma.Set();
}
/// <summary>
/// Web停止
/// </summary>
public void WebStop()
{
try
{
NeedStop = true;
Status = CaculateStatus.Stopping;
this.IsStop = true;
// 取消所有挂起的操作
_cancellationTokenSource.Cancel();
// 释放信号量,避免线程阻塞
ma.Set();
// 等待线程完成,设置超时防止无限等待
bool threadCompleted = ma.WaitOne(3000);
if (!threadCompleted)
{
// 记录日志:线程未能在预期时间内完成
Console.WriteLine("警告:计算线程未能在预期时间内停止");
}
}
catch (Exception ex)
{
// 记录异常
Console.WriteLine($"停止计算时发生异常: {ex.Message}");
}
finally
{
// 确保资源被释放
if (th != null && th.IsAlive)
{
Console.WriteLine("警告:计算线程仍在运行");
// 记录线程仍在运行
System.Diagnostics.Debug.WriteLine("警告:计算线程仍在运行");
}
}
}
/// <summary>
/// 保存部署图
/// </summary>
/// <param name="resultFile"></param>
public bool SaveResult(string resultFile)
{
if (nest == null || nest.PlacedPartsCount == 0)
{
// MessageBox.Show("未产生正确的结果!", "保存结果", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
string strExt = Path.GetExtension(resultFile).ToUpper();
if (strExt == ".DXF")
{
DxfParser.Export(resultFile, nest.Polygons.ToArray(), nest.Sheets.ToArray(), this.originX, this.originY);
}
else if (strExt == ".SVG")
{
SvgParser.Export(resultFile, nest.Polygons.ToArray(), nest.Sheets.ToArray());
}
else
{
return drawer.SaveAs(resultFile);
}
return true;
}
/// <summary>
/// 执行计算
/// </summary>
/// <param name="newWork"></param>
/// <returns></returns>
public bool Excute(bool newWork = true)
{
if (IsStop == false)
{
return false;
}
NeedStop = false;
if (newWork)
{
if (OpenDrawerFile() == null)
{
return false;
}
}
ma.Set();
//this.stlInfor.Text = string.Empty;
// 计算配置
if (CaculateParameter.SpecifyAngles == true)
{
nestConfig.SpecfiedAngles = CaculateParameter.SpeciaAngles.Select(it => (float)(it)).ToArray();
}
else
{ // 旋转角度角度
nestConfig.SpecfiedAngles = null;
// 部件旋转数
nestConfig.rotations = CaculateParameter.Rotations;
nestConfig.AngleStart = (float)CaculateParameter.AngleStart;
nestConfig.AngleEnd = (float)CaculateParameter.AngleEnd;
}
// 部件间间距设置
nestConfig.spacing = 0;// CaculateParameter.WellsSpace;
partSpacing = CaculateParameter.WellsSpace;
//this.borderFile = this.txtBorderFile.Text;
//this.faultageFile = this.txtFaultage.Text;
// 打开文件
// 加载边界数据
RawDetail detail = loadLayersDetail(this.BorderLayer);// loadDetail(this.borderFile);
detail.Name = this.BorderLayer;
if (detail.Outers.Count == 0)
{
return false;
}
if (detail.Outers.Count > 1)
{
detail.Outers.RemoveRange(1, detail.Outers.Count - 1);
}
// 计算相对坐标原点
var bbox = detail.BoundingBox();
originX = bbox.X;
originY = bbox.Y;
detail.Offset(-originX, -originY);
PathD pathBorder = new PathD();
foreach (var pt in detail.Outers[0].Points)
{
pathBorder.Add(new Clipper2Lib.PointD(pt.X, pt.Y));
}
// 加载断层数据
RawDetail detailFault = loadLayersDetail(this.FaultLayer);// loadDetail(this.faultageFile);
double dAreaFault = 0;
if (detailFault.Outers?.Count > 0)
{
detailFault.Offset(-originX, -originY);
PathsD paths = new PathsD(), solution;
double dMinFaultLength = CaculateParameter.MiniFaultLength;
foreach (var contour in detailFault.Outers)
{
// 忽略小断层
if (this.CaculateParameter.IgnoreMiniFault)
{
if (contour.Len <= dMinFaultLength)
{
continue;
}
}
PathD path = new PathD();
bool bOutBorder = true;
foreach (var pt in contour.Points)
{
Clipper2Lib.PointD ptd = new Clipper2Lib.PointD(pt.X, pt.Y);
if (Clipper2Lib.Clipper.PointInPolygon(ptd, pathBorder) == PointInPolygonResult.IsInside)
{
bOutBorder = false; // 一旦有一个点在内部,则线不在边界外部
}
path.Add(new Clipper2Lib.PointD(pt.X, pt.Y));
}
// 排除边界外断层
if (bOutBorder == false)
{
paths.Add(path);
}
}
// 断层线外扩成多边形,宽度可调
solution = Clipper.InflatePaths(paths, faultInflate, Clipper2Lib.JoinType.Round, Clipper2Lib.EndType.Round);
solution = Clipper.SimplifyPaths(solution, 2.5);
dAreaFault = Clipper2Lib.Clipper.Area(solution);
// 多边形添加到边界
foreach (var pathChild in solution)
{
LocalContour contourChild = new LocalContour();
foreach (var pt in pathChild)
{
contourChild.Points.Add(new PointF((float)pt.x, (float)pt.y));
}
detail.Outers.Add(contourChild);
}
}
//bbox = detail.BoundingBox();
// 二次部井
if (this.WellParameters.DeployAgain)
{
// 加载井组数据
RawDetail detailWells = loadWellGroupDetail("井组");
// 相对原点进行坐标偏移
detailWells.Offset(-originX, -originY);
// 区域外扩
PathsD paths = new PathsD(), solution;
foreach (var contour in detailWells.Outers)
{
PathD path = new PathD();
bool bOutBorder = true;
foreach (var pt in contour.Points)
{
Clipper2Lib.PointD ptd = new Clipper2Lib.PointD(pt.X, pt.Y);
if (Clipper2Lib.Clipper.PointInPolygon(ptd, pathBorder) == PointInPolygonResult.IsInside)
{
bOutBorder = false; // 一旦有一个点在内部,则线不在边界外部
}
path.Add(new Clipper2Lib.PointD(pt.X, pt.Y));
}
// 排除边界外断层
if (bOutBorder == false)
{
if (Math.Abs(path.First().x - path.Last().x) > 1E-4 || Math.Abs(path.First().y - path.Last().y) > 1E-4)
{
path.Add(new Clipper2Lib.PointD(path.First().x, path.First().y));
}
paths.Add(path);
}
}
// 断层线外扩成多边形,宽度可调
solution = Clipper.InflatePaths(paths, this.partSpacing * 0.5, JoinType.Miter, EndType.Polygon);
solution = Clipper.SimplifyPaths(solution, 2.5);
// 统计约束区面积
dAreaFault += Clipper2Lib.Clipper.Area(solution);
// 多边形添加到边界
foreach (var pathChild in solution)
{
LocalContour contourChild = new LocalContour();
foreach (var pt in pathChild)
{
contourChild.Points.Add(new PointF((float)pt.x, (float)pt.y));
}
detail.Outers.Add(contourChild);
}
}
NFP nfp = detail.ToNfp();
nest = new NestingContext();
int src = nest.GetNextSheetSource();
var ns = Background.clone(nfp);
Sheet sheet = new Sheet();
sheet.Points = ns.Points;
sheet.children = ns.children;
nest.Sheets.Add(sheet);
sheet.Width = sheet.WidthCalculated;
sheet.Height = sheet.HeightCalculated;
sheet.source = src;
nest.ReorderSheets();
// 边界的面积
double dAreaBorder = Clipper2Lib.Clipper.Area(pathBorder);
// 生成双侧井组
DrawerWellGroup wellGroupSide2 = new DrawerWellGroup();
this.groupParaSide2 = new WellGroupParameter();
this.groupParaSide2.WellPoint.X = 0;
this.groupParaSide2.WellPoint.Y = 0;
this.groupParaSide2.WellPoint.Z = 0;
this.groupParaSide2.WellPoint.Name = this.WellParameters.WellNamePrefix;
wellGroupSide2.Name = this.WellParameters.WellNamePrefix;
this.groupParaSide2.BranchDistanceRight = this.WellParameters.BranchOffset;
this.groupParaSide2.BranchDistanceLeft = this.groupParaSide2.BranchDistanceRight;
this.groupParaSide2.BranchAngle = 0.0;
this.groupParaSide2.BranchSpace = this.WellParameters.BranchSpace;
this.groupParaSide2.BranchLength = this.WellParameters.BranchLength;
this.groupParaSide2.BranchCountRight = this.WellParameters.BranchCount;
this.groupParaSide2.BranchCountLeft = this.groupParaSide2.BranchCountRight;
wellGroupSide2.Parameter = this.groupParaSide2.Clone();
bool bSuccess = wellGroupSide2.CreateHorizionWells();
// 生成单侧井组
this.groupParaSide1 = this.groupParaSide2.Clone();
this.groupParaSide1.BranchCountLeft = 0;
DrawerWellGroup wellGroupSide1 = new DrawerWellGroup();
wellGroupSide1.Parameter = groupParaSide1.Clone();
wellGroupSide1.CreateHorizionWells();
wellBox2 = CreateWellGroupBorder(wellGroupSide2, this.partSpacing);
wellBox1 = CreateWellGroupBorder(wellGroupSide1, this.partSpacing);
//List<RawDetail> shapes = new List<RawDetail>();
int nCountSide2 = 0;
if (this.WellParameters.DeploySide2 == true)
{
RawDetail detail2 = new RawDetail();
detail2.Outers.Add(wellBox2);
detail2.Name = "双侧";
PathD pathSide2 = new PathD();
foreach (var pt in wellBox2.Points)
{
pathSide2.Add(new Clipper2Lib.PointD(pt.X, pt.Y));
}
double dAreaSide2 = Clipper2Lib.Clipper.Area(pathSide2);
nCountSide2 = (int)Math.Abs((Math.Abs(dAreaBorder) - Math.Abs(dAreaFault)) / dAreaSide2);
for (int i = 0; i < nCountSide2; i++)
{
nest.ImportFromRawDetail(detail2, 0);
}
}
if (WellParameters.DeploySide1 == true)
{
RawDetail detail1 = new RawDetail();
detail1.Outers.Add(wellBox1);
detail1.Name = "单侧";
// 根据不同情况计算单侧方式井部署的数量
if (this.WellParameters.DeploySide2 == true)
{
int nCountSide1 = (int)(nCountSide2 * 0.35);
for (int i = 0; i < nCountSide1; i++)
{
nest.ImportFromRawDetail(detail1, 1);
}
}
else
{
PathD pathSide1 = new PathD();
foreach (var pt in wellBox1.Points)
{
pathSide1.Add(new Clipper2Lib.PointD(pt.X, pt.Y));
}
double dAreaSide1 = Clipper2Lib.Clipper.Area(pathSide1);
int nCountSide1 = (int)Math.Abs((Math.Abs(dAreaBorder) - Math.Abs(dAreaFault)) / dAreaSide1);
for (int i = 0; i < nCountSide1; i++)
{
nest.ImportFromRawDetail(detail1, 1);
}
}
}
// 设置突变率
nestConfig.mutationRate = (int)(nest.Polygons.Count * this.CaculateParameter.MutationRate);
nest.ReorderSheets();
nest.Config = this.nestConfig;
IsStop = false;
return run();
}
private bool run()
{
if (nest.Polygons.Count == 0 || nest.Sheets.Count == 0)
{
//MessageBox.Show("There are no sheets or parts", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
IsStop = true;
return false;
}
Background.UseParallel = true;
GeneticAlgorithm.StrictAngles = false;
return RunDeepnest();
}
Thread th;
//internal void displayProgress(float progress)
//{
// // progressVal = progress;
//}
private bool RunDeepnest()
{
if (th != null) return false;
// 重置取消令牌源
_cancellationTokenSource = new CancellationTokenSource();
var token = _cancellationTokenSource.Token;
th = new Thread(() =>
{
try
{
nest.StartNest();
while (!token.IsCancellationRequested)
{
this.Status = CaculateStatus.Paused;
if (IsStop)
{
this.Status = CaculateStatus.Stopped;
break;
}
// 检查取消令牌
if (token.IsCancellationRequested)
{
this.Status = CaculateStatus.Stopped;
break;
}
// 根据是否收到信号判断是否阻塞当前线程
ma.WaitOne();
if (IsStop || token.IsCancellationRequested)
{
this.Status = CaculateStatus.Stopped;
break;
}
Stopwatch sw = new Stopwatch();
sw.Start();
this.Status = CaculateStatus.Working;
nest.NestIterate();
sw.Stop();
IterateEvent?.Invoke(nest.Nest.nests, nest.MaterialUtilization, sw.ElapsedMilliseconds);
if (ExportPlaceMentsEvent != null)
{
ExportPlaceMents();
}
}
}
catch (OperationCanceledException)
{
// 正常取消操作,不需要特殊处理
this.Status = CaculateStatus.Stopped;
}
catch (Exception ex)
{
// 记录异常
Console.WriteLine($"计算线程发生异常: {ex.Message}");
this.Status = CaculateStatus.Stopped;
}
finally
{
th = null;
}
});
th.IsBackground = true;
th.Start();
return true;
}
private bool isDrawing = false;
/// <summary>
/// 生成部署图和部署信息
/// </summary>
/// <param name="placementIndex">方案的索引</param>
/// <param name="image">输出的部署图片</param>
/// <param name="info">输出的部署信息</param>
/// <returns></returns>
public bool CreatePlacementImage(int placementIndex, out Bitmap image, out string info)
{
if(nest.Nest.nests.Count<= placementIndex)
{
image = null;
info = null;
return false;
}
SheetPlacement placement = nest.Nest.nests[placementIndex];
nest.AssignPlacement(placement);
if(exportPlacementImage(out image, out info))
{
return true;
}
return false;
}
/// <summary>
/// 生成部署图和部署信息
/// </summary>
/// <param name="image"></param>
/// <param name="info"></param>
/// <returns></returns>
private bool exportPlacementImage(out Bitmap image, out string info)
{
image = null;
info = null;
if (isDrawing)
{
return false;
}
isDrawing = true;
StringBuilder strbStatistic = new StringBuilder();
foreach (var kv in nest.PartsStatistic)
{
strbStatistic.Append($"{kv.Key}:{kv.Value}个 ");
}
info = $"覆盖率: {Math.Round(nest.MaterialUtilization * 100.0f, 2)}% {strbStatistic}";
CoverageRate = Math.Round(nest.MaterialUtilization * 100.0f, 2);
addSymbols(drawer);
// 删除已有井组
// if (this.WellParameters.DeploySide2 == true)
{
//drawer.DeleteLayer(new string[1] { "井组\\双侧" }, true);
drawer.DeleteLayerElement( "井组\\双侧" , true);
}
// if (this.WellParameters.DeploySide1 == true)
{
drawer.DeleteLayerElement("井组\\单侧", true);
//drawer.DeleteLayer(new string[1] { "井组\\单侧" }, true);
}
if (sourceWellGroups?.Count > 0)
{
foreach (var groupItem in sourceWellGroups)
{
drawer.AddWellGroup(groupItem.Item1, groupItem.Item2);
}
}
//drawer.DeleteLayerElement( "井组" , true);
// 部件内缩距离
float fSpace = (float)(partSpacing * 0.5);
// 断层外扩距离
float fFaultExpand = fSpace;
List<PointF> box1 = new List<PointF>();
box1.AddRange(new PointF[5] {
new PointF(wellBox1.Points[0].X+fSpace, wellBox1.Points[0].Y+fSpace),
new PointF(wellBox1.Points[1].X-fSpace, wellBox1.Points[1].Y+fSpace),
new PointF(wellBox1.Points[2].X-fSpace, wellBox1.Points[2].Y-fSpace),
new PointF(wellBox1.Points[3].X+fSpace, wellBox1.Points[3].Y-fSpace),
new PointF(wellBox1.Points[4].X+fSpace, wellBox1.Points[4].Y+fSpace) });
List<PointF> box2 = new List<PointF>();
box2.AddRange(new PointF[] {
new PointF(wellBox2.Points[0].X+fSpace, wellBox2.Points[0].Y+fSpace),
new PointF(wellBox2.Points[1].X-fSpace, wellBox2.Points[1].Y+fSpace),
new PointF(wellBox2.Points[2].X-fSpace, wellBox2.Points[2].Y-fSpace),
new PointF(wellBox2.Points[3].X+fSpace, wellBox2.Points[3].Y-fSpace),
new PointF(wellBox2.Points[4].X+fSpace, wellBox2.Points[4].Y+fSpace)});
//this.resultFile = this.txtResultFile.Text;
//string strExt = Path.GetExtension(resultFile).ToUpper();
List<Tuple<NFP, int>> lstWells = new List<Tuple<NFP, int>>();
HashSet<int> removedIndices = DfdParser.ExportPlacements(nest.Polygons, nest.Sheets.ToArray(), this.originX, this.originY, (polygon, wellType) =>
{
// 断层外扩处理
if (wellType == 2) //strName == "断层")
{
PathsD paths = new PathsD(), solution;
PathD path = new PathD();
foreach (var pt in polygon.Points)
{
path.Add(new Clipper2Lib.PointD(pt.x, pt.y));
}
paths.Add(path);
// 断层线外扩成多边形,宽度可调
solution = Clipper.InflatePaths(paths, fFaultExpand, JoinType.Round, EndType.Round);
solution = Clipper.SimplifyPaths(solution, 2.5);
if (solution.Count > 0)
{
PointF[] pts = solution[0].Select(it => new PointF((float)it.x, (float)it.y)).ToArray();
return pts;
}
return null;
}
else if (wellType == 0) //strName.Equals("双侧"))
{
lstWells.Add(new Tuple<NFP, int>(polygon, wellType));
// polygon内缩处理
return box2.ToArray();
}
else if (wellType == 1) //strName.Equals("单侧"))
{
lstWells.Add(new Tuple<NFP, int>(polygon, wellType));
return box1.ToArray();
}
return null;
});
if (lstWells.Count > 0)
{
SingleWell = 0;// 计数器清零
DoubleWell = 0;// 计数器清零
string strWellName = this.WellParameters.WellNamePrefix;
//DrawerData drawer = new DrawerData();
for (int i = 0; i < lstWells.Count; i++)
{
if (removedIndices.Contains(i)) { continue; }
Tuple<NFP, int> well = lstWells[i];
string strElementData = string.Empty;
if (well.Item2 == 0)
{ // 双侧井组
DrawerWellGroup wellGroupSide2 = new DrawerWellGroup();
wellGroupSide2.Parameter = this.groupParaSide2.Clone();
wellGroupSide2.Parameter.BranchAngle = well.Item1.rotation;
wellGroupSide2.Name = $"{strWellName}{i + 1}";
wellGroupSide2.CreateHorizionWells();
setWellGroupStyle(wellGroupSide2);
wellGroupSide2.Offset(this.originX, this.originY);
wellGroupSide2.Offset(well.Item1.x, well.Item1.y);
DrawerElementProperty element = new DrawerElementProperty();
element.Element = wellGroupSide2;
element.ElementType = wellGroupSide2.ElementType;
strElementData = DrawerElementHelp.Serialize(element);
drawer.AddWellGroup("井组\\双侧", strElementData);
DoubleWell++;
}
else
{ // 单侧井组
//wellGroupSide1.Angle = well.Item1.rotation + 90;
DrawerWellGroup wellGroupSide1 = new DrawerWellGroup();
wellGroupSide1.Name = $"{strWellName}{i + 1}";
wellGroupSide1.Parameter = this.groupParaSide1.Clone();
wellGroupSide1.Parameter.BranchAngle = well.Item1.rotation;
wellGroupSide1.CreateHorizionWells();
setWellGroupStyle(wellGroupSide1);
wellGroupSide1.Offset(this.originX, this.originY);
wellGroupSide1.Offset(well.Item1.x, well.Item1.y);
DrawerElementProperty element = new DrawerElementProperty();
element.Element = wellGroupSide1;
element.ElementType = wellGroupSide1.ElementType;
strElementData = DrawerElementHelp.Serialize(element);
drawer.AddWellGroup("井组\\单侧", strElementData);
SingleWell++;
}
}
}
IntPtr hBmp = drawer.GetBitmapHandle(this.ImageWidth, this.ImageHeight, 0);
image = System.Drawing.Image.FromHbitmap(hBmp);
image.MakeTransparent(Color.White);
//this.pictureBox1.Image = bmp;
drawer.DeleteHbmp(hBmp);
//this.ExportPlaceMentsEvent?.Invoke(bmp, strInfo);
isDrawing = false;
return true;
}
/// <summary>
/// 导出部署图
/// </summary>
private void ExportPlaceMents()
{
if(exportPlacementImage(out Bitmap image, out string info))
{
this.ExportPlaceMentsEvent?.Invoke(image, info);
}
}
/// <summary>
/// 设置进组的显示样式
/// </summary>
/// <param name="wellGroup">井组</param>
private void setWellGroupStyle(DrawerWellGroup wellGroup)
{
// 设置井点样式
DrawerPointStyle ptstyleWell = new DrawerPointStyle();
ptstyleWell.AlignHorizion = (int)TextStyleFlags.alignCenterH;
ptstyleWell.AlignVertical = (int)TextStyleFlags.alignTop;
ptstyleWell.Offset = new PropertyPoint(0, 50);
PropertySize txtSize = default(PropertySize);
txtSize.Width = 100 * 0.4;
txtSize.Height = 100;
txtSize.FixScale = true;
SizeF sizeSymbol = new SizeF(100f, 100f);
ptstyleWell.TextSize = txtSize;
ptstyleWell.SymbolSize = sizeSymbol;
ptstyleWell.SymbolName = "井点";
wellGroup.WellPointStyle = ptstyleWell;
// 设置井支入靶点和出靶点样式
DrawerPointStyle ptStart = ptstyleWell.Clone();
ptStart.Name = "start";
ptStart.SymbolName = "入靶点";
ptStart.SymbolSize = new SizeF((float)(sizeSymbol.Width * 0.5), (float)(sizeSymbol.Height * 0.5));
DrawerPointStyle ptEnd = ptstyleWell.Clone();
ptEnd.Name = "end";
ptEnd.SymbolName = "出靶点";
ptEnd.SymbolSize = new SizeF((float)(sizeSymbol.Width * 0.5), (float)(sizeSymbol.Height * 0.5));
DrawerCurveStyle drawerCurveStyleOffset = new DrawerCurveStyle();
drawerCurveStyleOffset.Name = "offset";
CurveProperty curvePropertyOffset = new CurveProperty();
curvePropertyOffset.Width = 5;
curvePropertyOffset.LineColor = Color.Black;
drawerCurveStyleOffset.Properties.Add(curvePropertyOffset);
DrawerCurveStyle drawerCurveStyleHori = new DrawerCurveStyle();
drawerCurveStyleHori.Name = "horizon";
CurveProperty curvePropertyHori = new CurveProperty();
curvePropertyHori.Width = 5;
curvePropertyHori.LineColor = Color.Black;
drawerCurveStyleHori.Properties.Add(curvePropertyHori);
List<DrawerCurveStyle> lineStyles = new List<DrawerCurveStyle>
{
drawerCurveStyleOffset,
drawerCurveStyleHori
};
int nBranchAllCount = wellGroup.WellBranches.Count;
for (int i = 0; i < nBranchAllCount; i++)
{
WellBranch branch = wellGroup.WellBranches[i];
branch.PointStyles = new List<DrawerPointStyle>
{
ptStart,
ptEnd
};
branch.PointStart.Name = $"{wellGroup.Name}-{i + 1}A";
branch.PointEnd.Name = $"{wellGroup.Name}-{i + 1}B";
branch.LineStyles = lineStyles;
}
}
/// <summary>
/// 添加进组所需符号
/// </summary>
/// <param name="drawer"></param>
private void addSymbols(DrawerData drawer)
{
string strSymbolWell = @"Layer M 0
Pline
-0.5,-0.5
-0.5,0.5
0.5,0.5
0.5,-0.5
-0.5,-0.5
";
drawer.AddDataAsSymble(strSymbolWell, "井点", false);
strSymbolWell = @"Layer M 0
_Ellipse
0,0
0.5,0.5
0.5 4
";
drawer.AddDataAsSymble(strSymbolWell, "入靶点", false);
strSymbolWell = @"Layer M 0
_Ellipse
0,0
0.5,0.5
0.5 4
";
drawer.AddDataAsSymble(strSymbolWell, "出靶点", false);
}
/// <summary>
/// 加载线数据
/// </summary>
/// <param name="layers"></param>
/// <returns></returns>
private RawDetail loadLayersDetail(string layers)
{
string[] saFullLayers = Regex.Split(layers, ",");
RawDetail rawDetail = new RawDetail();
// 遍历每一个图层
foreach (string layer in saFullLayers)
{
string curveData = string.Empty;
int nCount = drawer.LayerGetCurves(layer, ref curveData, false);
if (nCount == 0)
{
continue;
}
DrawerElementHelp elementHelp = new DrawerElementHelp();
List<DrawerElementProperty> propertys = elementHelp.DeserializeList(curveData);
if(propertys == null)
{
continue;
}
// 生成每一条线
foreach (DrawerElementProperty eleProperty in propertys)
{
DrawerPline blockLine = eleProperty.Element as DrawerPline;
if (blockLine == null)
{
continue;
}
string[] saCoorLine = Regex.Split(blockLine.Coordinate, "\r\n");
if (saCoorLine.Length > 1)
{
// 生成每一个坐标点
List<PointF> points = new List<PointF>();
foreach (string strLine in saCoorLine)
{
string[] saCoor = strLine.Split(',');
if (saCoor.Length > 1)
{
points.Add(new PointF(float.Parse(saCoor[0]), float.Parse(saCoor[1])));
}
}
if (points.Count > 0)
{
rawDetail.Outers.Add(new LocalContour() { Points = points });
}
}
}
}
return rawDetail;
}
private List<Tuple<string, string>> sourceWellGroups = new List<Tuple<string, string>>();
/// <summary>
/// 加载井组的轮廓数据
/// </summary>
/// <param name="layers"></param>
/// <returns></returns>
private RawDetail loadWellGroupDetail(string layers)
{
sourceWellGroups = new List<Tuple<string, string>>();
RawDetail rawDetail = new RawDetail();
long[] laPos = this.drawer.SearchElementByType((int)DrawElementType.ELEMENT_WELL_GROUP);
if(laPos == null)
{
return rawDetail;
}
foreach (long pos in laPos)
{
NFP nfpHull = new NFP();
List<SvgPoint> lstPt = new List<SvgPoint>();
string strElementData = this.drawer.GetElementByPosition(pos);
DrawerElementProperty property = DrawerElementHelp.Deserialize(strElementData);
//Trace.TraceInformation(strElementData);
//Trace.TraceWarning(strElementData);
sourceWellGroups.Add(new Tuple<string, string>(property.Layer, strElementData));
DrawerWellGroup wellGroup = property.Element as DrawerWellGroup;
lstPt.Add(new SvgPoint(wellGroup.X, wellGroup.Y));
foreach (WellBranch branch in wellGroup.WellBranches)
{
lstPt.Add(new SvgPoint(branch.PointStart.X, branch.PointStart.Y));
lstPt.Add(new SvgPoint(branch.PointEnd.X, branch.PointEnd.Y));
}
nfpHull.Points = lstPt;
NFP hull = Background.getHull(nfpHull);
LocalContour contourHull = new LocalContour();
contourHull.Points = new List<PointF>(hull.Points.Select(it => new PointF((float)it.x, (float)it.y)));
rawDetail.Outers.Add(contourHull);
}
return rawDetail;
}
private static LocalContour CreateWellGroupBorder(DrawerWellGroup wellGroup, double spacing)
{
RectangleD rect = wellGroup.CaculateDataRange();
float dSpacing = (float)(spacing * 0.5);
List<PointF> shapePoints = new List<PointF>();
shapePoints.AddRange(new PointF[5] {
new PointF((float)rect.Left-dSpacing, (float)rect.Top-dSpacing),
new PointF((float)rect.Right+dSpacing, (float)rect.Top-dSpacing),
new PointF((float)rect.Right+dSpacing, (float)rect.Bottom+dSpacing),
new PointF((float)rect.Left-dSpacing, (float)rect.Bottom+dSpacing),
new PointF((float)rect.Left-dSpacing, (float)rect.Top-dSpacing),
});
LocalContour contour = new LocalContour()
{
Points = shapePoints,
};
return contour;
}
}
// public enum CaculateStatus
// {
// None = 0,
// Stopping =1,
// Stopped = 2,
// Pausing = 3,
// Paused = 4,
// Working =5,
// }
}