using Clipper2Lib;
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 System.Threading.Tasks;
using System.Windows.Forms;
using DrawerData = GeoSigmaDrawLib.DrawerData;
namespace SmartWells
{
public partial class Form1 : Form
{
private NestingContext nest;
private double originX = 0;
private double originY = 0;
private string borderFile = string.Empty;
private string faultageFile = string.Empty;
private string resultFile = string.Empty;
private string mapFile;
double partSpacing = 200;
double faultInflate = 10;
private bool stop = true;
WellGroupParameter groupParaSide2;
WellGroupParameter groupParaSide1;
LocalContour wellBox2;
LocalContour wellBox1;
DrawerData drawer;// = new DrawerData();
///
/// 控制执行线程
///
ManualResetEvent ma = new ManualResetEvent(false);
SvgNestConfig nestConfig;
CaculateHelp caculator;
private bool newDeployFile = true;
public Form1()
{
InitializeComponent();
toolStripProgressBar1.Width = statusStrip1.Width - stlInfor.Width - 20;
nestConfig = new SvgNestConfig();
caculator = new CaculateHelp();
caculator.IterateEvent += updatePlacementsInfo;
caculator.ExportPlaceMentsEvent += updateDeployImage;
}
///
/// 打开工区图件
///
/// 事件按钮
/// 事件参数
private void btnMap_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "*.kev|*.kev|*.dfd|*.dfd";
ofd.Multiselect = false;
ofd.RestoreDirectory = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
this.txtMap.Text = ofd.FileName;
}
}
///
/// 打开文件
///
/// 文件全路径
///
private async Task OpenDrawerFile(string fileName)
{
if (!File.Exists(fileName))
{
return false;
}
bool bResult = false;
await Task.Run(() =>
{
if (drawer != null)
{
drawer.Dispose();
drawer = null;
}
drawer = new DrawerData();
drawer.OpenWithDraw = true;
try
{
if (drawer.OpenFile(mapFile))
{
bResult = true;
}
}
catch (Exception ex)
{
drawer.Dispose();
drawer = null;
bResult = false;
}
});
return bResult;
}
private async void txtMap_TextChanged(object sender, EventArgs e)
{
if (this.stop)
{
mapFile = this.txtMap.Text;
await OpenDrawerFile(mapFile);
}
newDeployFile = true;
}
///
/// 边界文件
///
///
///
private async void btnBorderFile_Click(object sender, EventArgs e)
{
if(drawer == null)
{
mapFile = this.txtMap.Text;
bool bOpen = await this.OpenDrawerFile(mapFile);
if (bOpen == false)
{
return;
}
}
string strLayers = drawer.GetLayers();
FormLayers frmLayers = new FormLayers(strLayers);
if(frmLayers.ShowDialog(this)== DialogResult.OK)
{
List lstChecked = frmLayers.SelectedNodes;
if(lstChecked!=null && lstChecked.Count > 0)
{
this.txtBorderFile.Text = string.Join(",", lstChecked);
}
}
}
private async void btnFaultFile_Click(object sender, EventArgs e)
{
if (drawer == null)
{
mapFile = this.txtMap.Text;
bool bOpen = await this.OpenDrawerFile(mapFile);
if (bOpen == false)
{
return;
}
}
string strLayers = drawer.GetLayers();
FormLayers frmLayers = new FormLayers(strLayers);
if (frmLayers.ShowDialog(this) == DialogResult.OK)
{
List lstChecked = frmLayers.SelectedNodes;
if (lstChecked != null && lstChecked.Count > 0)
{
this.txtFaultage.Text = string.Join(",", lstChecked);
}
}
}
///
/// 结果文件
///
///
///
private void btnResultFile_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Dxf files (*.dxf)|*.dxf|Svg files (*.svg)|*.svg|*.dfd|*.dfd";
sfd.FilterIndex = lastSaveFilterIndex;
sfd.AddExtension = true;
//sfd.RestoreDirectory = true;
if (sfd.ShowDialog() == DialogResult.OK)
{
lastSaveFilterIndex = sfd.FilterIndex;
this.txtResultFile.Text = sfd.FileName;
}
}
int lastSaveFilterIndex = 3;
private void btnOutput_Click(object sender, EventArgs e)
{
//if (nest == null || nest.PlacedPartsCount == 0)
//{
// MessageBox.Show("未产生正确的结果!", "保存结果", MessageBoxButtons.OK, MessageBoxIcon.Error);
// return;
//}
//SaveResult();
this.resultFile = this.txtResultFile.Text;
if (this.caculator.SaveResult(this.resultFile))
{
MessageBox.Show("保存成功!");
}
else
{
MessageBox.Show("未产生正确的结果!", "保存结果", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void SaveResult()
{
this.resultFile = this.txtResultFile.Text;
string strExt = Path.GetExtension(resultFile).ToUpper();
if (strExt == ".DFD")
{
drawer.SaveAs(this.resultFile);
}
else 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());
}
}
private void btnPause_Click(object sender, EventArgs e)
{
if (this.btnPause.Text == "暂停")
{
this.caculator.Pause();
}
else
{
this.caculator.Continue();
}
//// 信号关闭阻,塞当前线程
//if (btnPause.Text == "暂停")
//{
// btnPause.Text = "等待暂停";
// this.btnPause.Enabled = false;
// ma.Reset();
//}
//else if(btnPause.Text =="继续")
//{
// btnPause.Text = "暂停";
// // 信号打开,不阻塞当前线程
// ma.Set();
//}
}
private void btnStop_Click(object sender, EventArgs e)
{
//stop = true;
//btnStop.Text = "等待停止";
//btnPause_Click(null, null);
this.caculator.Stop();
}
private WellsConfig makeWellConfig()
{
WellsConfig wellsConfig = new WellsConfig();
wellsConfig.WellNamePrefix = this.txtWellName.Text;
if(int.TryParse(this.txtBranchCount.Text, out int count)
&& double.TryParse(this.txtBranchDistance.Text, out double offset)
&& double.TryParse(this.txtBranchLength.Text, out double length)
&& double.TryParse(this.txtBranchSpace.Text, out double space))
{
wellsConfig.BranchCount = count;
wellsConfig.BranchOffset = offset;
wellsConfig.BranchLength = length;
wellsConfig.BranchSpace = space;
}
else
{
return null;
}
wellsConfig.DeploySide2 = ckbSide2.Checked;
wellsConfig.DeploySide1 = ckbSide1.Checked;
wellsConfig.DeployAgain = this.ckbReDeployment.Checked;
return wellsConfig;
}
private CaculateConfig makeCaculateConfig()
{
CaculateConfig caculateConfig = new CaculateConfig();
if (double.TryParse(this.txtPartsSpace.Text, out double partSpace)
&& double.TryParse(this.txtMutationRate.Text, out double mutation))
{
caculateConfig.WellsSpace = partSpace;
caculateConfig.MutationRate = mutation;
}
else
{
return null;
}
if (this.rdbRotationTimes.Checked)
{
if (int.TryParse(this.txtRotationTimes.Text, out int rotationTimes)
&& double.TryParse(this.txtAngleStart.Text, out double angleStart)
&& double.TryParse(this.txtAngleEnd.Text, out double angleEnd))
{
caculateConfig.SpecifyAngles = false;
caculateConfig.Rotations = rotationTimes;
caculateConfig.AngleStart = angleStart;
caculateConfig.AngleEnd = angleEnd;
}
else { return null; }
}
if (this.rdbRotationAngles.Checked)
{
List specfiedAngles = new List();
foreach (string strLine in txtRotationAngles.Lines)
{
string[] saLine = strLine.Split(',');
foreach (string strItem in saLine)
{
double fAngle = 0;
if (double.TryParse(strItem, out fAngle))
{
specfiedAngles.Add(fAngle);
}
}
}
caculateConfig.SpecifyAngles = true;
caculateConfig.SpeciaAngles = specfiedAngles.ToArray();
}
caculateConfig.IgnoreMiniFault = ckbMiniFaultLength.Checked;
if (ckbMiniFaultLength.Checked)
{
caculateConfig.MiniFaultLength = double.TryParse(this.txtMinFaultLength.Text, out double miniLength) ? miniLength : 1000;
}
return caculateConfig;
}
///
/// 执行计算
///
///
///
private void btnPlay_Click(object sender, EventArgs e)
{
string strDeployFile = this.txtMap.Text;
string strBorderLayer = this.txtBorderFile.Text;
string strFaultLayer = this.txtFaultage.Text;
WellsConfig wellsConfig = makeWellConfig();
CaculateConfig caculateConfig = makeCaculateConfig();
this.caculator.DeployFile = strDeployFile;
this.caculator.BorderLayer = strBorderLayer;
this.caculator.FaultLayer = strFaultLayer;
this.caculator.WellParameters = wellsConfig;
this.caculator.CaculateParameter = caculateConfig;
this.caculator.ImageWidth = this.pictureBox1.Width;
this.caculator.ImageHeight = this.pictureBox1.Height;
bool bReopenDraw = newDeployFile;
newDeployFile = false;
this.caculator.DisplayProgressAction = displayProgress;
if (this.caculator.Excute(bReopenDraw) == false)
{
MessageBox.Show("执行错误!", this.Text);
}
return;
if (stop == true)
{
this.btnPlay.Enabled = false;
stop = false;
this.btnPause.Enabled = true;
ma.Set();
}
else
{
return;
}
this.stlInfor.Text = string.Empty;
// 计算配置
// 部件旋转数
if (rdbRotationTimes.Checked)
{
nestConfig.SpecfiedAngles = null;
int nRotations = 8;
if (int.TryParse(this.txtRotationTimes.Text, out nRotations))
{
nestConfig.rotations = nRotations;
}
if (float.TryParse(this.txtAngleStart.Text, out float fAngleStart))
{
nestConfig.AngleStart = fAngleStart;
}
if (float.TryParse(this.txtAngleEnd.Text, out float fAngleEnd))
{
nestConfig.AngleEnd = fAngleEnd;
}
}
else if (this.rdbRotationAngles.Checked)
{
List specfiedAngles = new List();
foreach(string strLine in txtRotationAngles.Lines)
{
string[] saLine = strLine.Split(',');
foreach(string strItem in saLine)
{
float fAngle = 0;
if(float.TryParse(strItem, out fAngle))
{
specfiedAngles.Add(fAngle);
}
}
}
nestConfig.SpecfiedAngles = specfiedAngles.ToArray();
}
// 部件间间距设置
double dSpacing = 0;
if (double.TryParse(this.txtPartsSpace.Text, out dSpacing))
{
nestConfig.spacing = 0;
partSpacing = dSpacing;
}
this.borderFile = this.txtBorderFile.Text;
this.faultageFile = this.txtFaultage.Text;
// 加载边界数据
RawDetail detail = loadLayersDetail(this.borderFile);// loadDetail(this.borderFile);
detail.Name = borderFile;
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));
}
double dMinFaultLength = 1000;
if(!double.TryParse(this.txtMinFaultLength.Text, out dMinFaultLength))
{
dMinFaultLength = 0;
}
// 加载断层数据
RawDetail detailFault = loadLayersDetail(this.faultageFile);// loadDetail(this.faultageFile);
double dAreaFault = 0;
if (detailFault.Outers?.Count>0)
{
detailFault.Offset(-originX, -originY);
PathsD paths = new PathsD(), solution;
foreach (var contour in detailFault.Outers)
{
// 忽略小断层
if (this.ckbMiniFaultLength.Checked)
{
//double dLineLength = CaculateLineLength(path);
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, JoinType.Round, 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.ckbReDeployment.Checked)
{
// 加载井组数据
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);
//StringBuilder strbMsg = new StringBuilder();
//foreach(var line in solution)
//{
// strbMsg.AppendLine("Pline");
// foreach (var pt in line)
// {
// strbMsg.AppendLine($"{pt.x},{pt.y}");
// }
// strbMsg.AppendLine();
//}
//Trace.WriteLine(strbMsg.ToString());
// 统计约束区面积
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.txtWellName.Text;
wellGroupSide2.Name = this.txtWellName.Text;
this.groupParaSide2.BranchDistanceRight = double.Parse(this.txtBranchDistance.Text);
this.groupParaSide2.BranchDistanceLeft = this.groupParaSide2.BranchDistanceRight;
this.groupParaSide2.BranchAngle = 0.0;
this.groupParaSide2.BranchSpace = double.Parse(this.txtBranchSpace.Text);
this.groupParaSide2.BranchLength = double.Parse(this.txtBranchLength.Text);
this.groupParaSide2.BranchCountRight = int.Parse(txtBranchCount.Text);
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 shapes = new List();
int nCountSide2 = 0;
if (ckbSide2.Checked)
{
RawDetail detail2 = new RawDetail();
detail2.Outers.Add(wellBox2);
detail2.Name = "双侧";
//shapes.Add(detail2);
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 (ckbSide1.Checked)
{
RawDetail detail1 = new RawDetail();
detail1.Outers.Add(wellBox1);
detail1.Name = "单侧";
//shapes.Add(detail1);
if (ckbSide2.Checked)
{
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);
}
}
}
// 设置突变率
double dMutation = 0.5;
if(double.TryParse(this.txtMutationRate.Text, out dMutation))
{
nestConfig.mutationRate = (int)(nest.Polygons.Count * dMutation);
}
////loadShapesData(new List() { wellGroupSide1, wellGroupSide2});
////for(int i = 0; i < shapes.Count; i++)
////{
//// //shapes[i].Offset(-originX, -originY);
////}
//int nSrc = 0;
//for(int i = 0; i < shapes.Count; i++)
//{
// for (int j = 0; j < 20; j++)
// {
// nest.ImportFromRawDetail(shapes[i], nSrc);
// //nSrc++;
// }
// nSrc++;
//}
nest.ReorderSheets();
nest.Config = this.nestConfig;
run();
}
private void run()
{
if (nest.Polygons.Count == 0 || nest.Sheets.Count == 0)
{
MessageBox.Show("There are no sheets or parts", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Background.UseParallel = true;
GeneticAlgorithm.StrictAngles = false;
RunDeepnest();
}
Thread th;
public void RunDeepnest()
{
if (th != null) return;
th = new Thread(() =>
{
nest.DisplayProgressAction = displayProgress;
nest.StartNest();
//UpdateNestsList();
//Background.DisplayProgressAction = displayProgress;
while (true)
{
if (stop)
{
//btnPlay.Enabled = true;
displayProgress(0.0f);
break;
}
// 根据是否收到信号判断是否阻塞当前线程
ma.WaitOne();
if (stop)
{
writeUiSafe("");
//btnPlay.Enabled = true;
displayProgress(0.0f);
break;
}
Stopwatch sw = new Stopwatch();
sw.Start();
nest.NestIterate();
UpdatePreview();
UpdateNestsList();
displayProgress(1.0f);
sw.Stop();
string strInfo = $"利用率: {Math.Round(nest.MaterialUtilization * 100.0f, 2)}% 计算耗时: {sw.ElapsedMilliseconds}ms";
writeUiSafe(strInfo);
displayProgress(0.0f);
}
th = null;
});
th.IsBackground = true;
th.Start();
}
private void updateDeployImage(Bitmap bmp, string info)
{
if(this.InvokeRequired)
{
this.Invoke(new Action(() => {
updateDeployImage(bmp, info);
}));
return;
}
// bmp.MakeTransparent(Color.White);
this.pictureBox1.Image = bmp;
lblNestInfo.Text = info;
}
private void updatePlacementsInfo(List placements, double materialUtilization, long elapsedMilliseconds)
{
if (this.InvokeRequired)
{
Invoke(new Action(() =>
{
updatePlacementsInfo(placements, materialUtilization, elapsedMilliseconds);
}));
return;
}
lsvHistory.BeginUpdate();
lsvHistory.Items.Clear();
foreach (var item in placements)
{
lsvHistory.Items.Add(new ListViewItem(new string[] { item.fitness == null ? "(null)" : item.fitness.Value.ToString("N5") }) { Tag = item });
}
lsvHistory.EndUpdate();
string strInfo = $"利用率: {Math.Round(materialUtilization * 100.0f, 2)}% 计算耗时: {elapsedMilliseconds}ms";
stlInfor.Text = strInfo;
}
public void UpdateNestsList()
{
if (nest != null)
{
lsvHistory.Invoke((Action)(() =>
{
lsvHistory.BeginUpdate();
lsvHistory.Items.Clear();
foreach (var item in nest.Nest.nests)
{
lsvHistory.Items.Add(new ListViewItem(new string[] { item.fitness == null ? "(null)" : item.fitness.Value.ToString("N5") }) { Tag = item });
}
lsvHistory.EndUpdate();
}));
}
}
private bool isDrawing = false;
private void UpdatePreview()
{
if (isDrawing)
{
return;
}
if (this.InvokeRequired)
{
Invoke(new Action(() =>
{
UpdatePreview();
}));
}
else
{
isDrawing = true;
addSymbols(drawer);
// 删除已有井组
if (this.ckbSide2.Checked)
{
drawer.DeleteLayer(new string[1] { "井组\\双侧" }, true);
}
if (this.ckbSide1.Checked)
{
drawer.DeleteLayer(new string[1] { "井组\\单侧" }, true);
}
//drawer.DeleteLayerElement( "井组" , true);
// 部件内缩距离
float fSpace = (float)(partSpacing * 0.5);
// 断层外扩距离
float fFaultExpand = fSpace;
List box1 = new List();
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 box2 = new List();
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> lstWells = new List>();
HashSet 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(polygon, wellType));
// polygon内缩处理
return box2.ToArray();
}
else if (wellType == 1) //strName.Equals("单侧"))
{
lstWells.Add(new Tuple(polygon, wellType));
return box1.ToArray();
}
return null;
});
if (lstWells.Count > 0)
{
string strWellName = this.txtWellName.Text;
//DrawerData drawer = new DrawerData();
for (int i = 0; i < lstWells.Count; i++)
{
if (removedIndices.Contains(i)) { continue; }
Tuple 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);
}
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);
}
}
}
IntPtr hBmp = drawer.GetBitmapHandle(this.pictureBox1.Width, pictureBox1.Height, 0);
Bitmap bmp = Image.FromHbitmap(hBmp);
bmp.MakeTransparent(Color.White);
this.pictureBox1.Image = bmp;
drawer.DeleteHbmp(hBmp);
StringBuilder strbStatistic = new StringBuilder();
foreach (var kv in nest.PartsStatistic)
{
strbStatistic.Append($"{kv.Key}:{kv.Value}个 ");
}
lblNestInfo.Text = $"覆盖率: {Math.Round(nest.MaterialUtilization * 100.0f, 2)}% {strbStatistic}";
isDrawing = false;
}
}
///
/// 添加进组所需符号
///
///
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);
}
///
/// 设置进组的显示样式
///
/// 井组
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 lineStyles = new List
{
drawerCurveStyleOffset,
drawerCurveStyleHori
};
int nBranchAllCount = wellGroup.WellBranches.Count;
for (int i = 0; i < nBranchAllCount; i++)
{
WellBranch branch = wellGroup.WellBranches[i];
branch.PointStyles = new List
{
ptStart,
ptEnd
};
branch.PointStart.Name = $"{wellGroup.Name}-{i + 1}A";
branch.PointEnd.Name = $"{wellGroup.Name}-{i + 1}B";
branch.LineStyles = lineStyles;
}
}
private void lsvHistory_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (lsvHistory.SelectedItems.Count > 0)
{
int nIndex = lsvHistory.SelectedItems[0].Index;
if (caculator.CreatePlacementImage(nIndex, out Bitmap image, out string info))
{
updateDeployImage(image, info);
}
//var shp = lsvHistory.SelectedItems[0].Tag as SheetPlacement;
//nest.AssignPlacement(shp);
//UpdatePreview();
}
}
private void writeUiSafe(string infor)
{
if(this.InvokeRequired)
{
Invoke(new Action(() => {
writeUiSafe(infor);
}));
}
else
{
stlInfor.Text = infor;
if (stop)
{
this.btnStop.Text = "停止";
}
if (this.btnPause.Text == "等待暂停")
{
this.btnPause.Text = "继续";
this.btnPause.Enabled = true;
}
}
}
internal void displayProgress(float progress)
{
if(this.InvokeRequired)
{
Invoke(new Action(() =>
{
try
{
displayProgress(progress);
}
catch { }
}));
return;
}
int nValue = (int)Math.Round(progress * 100f);
if ( nValue == 100)
{
nValue = 0;
}
toolStripProgressBar1.Value = nValue;
toolStripProgressBar1.Control.CreateGraphics().DrawString($"{nValue}", this.Font, Brushes.Black,
toolStripProgressBar1.Width/2, 2);
// progressVal = progress;
}
private List loadShapesData(List wellGroups)
{
List rawDetails = new List();
foreach(DrawerWellGroup group in wellGroups)
{
LocalContour contour = CreateWellGroupBorder(group, this.partSpacing);
RawDetail detail = new RawDetail();
if (group.Parameter.BranchCountLeft > 0 && group.Parameter.BranchCountRight > 0)
{
detail.Name = "双侧";
}
else
{
detail.Name = "单侧";
}
detail.Outers.Add(contour);
rawDetails.Add(detail);
}
return rawDetails;
}
private static LocalContour CreateWellGroupBorder(DrawerWellGroup wellGroup, double spacing)
{
RectangleD rect = wellGroup.CaculateDataRange();
float dSpacing = (float)(spacing * 0.5);
List shapePoints = new List();
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;
}
///
/// 加载井组的轮廓数据
///
///
///
private RawDetail loadWellGroupDetail(string layers)
{
RawDetail rawDetail = new RawDetail();
//DrawerData drawerDetail = new DrawerData();
//drawerDetail.OpenFile(mapFile);
long[] laPos = this.drawer.SearchElementByType((int)DrawElementType.ELEMENT_WELL_GROUP);
foreach(long pos in laPos)
{
NFP nfpHull = new NFP();
List lstPt= new List();
string strElementData = this.drawer.GetElementByPosition(pos);
DrawerElementProperty property = DrawerElementHelp.Deserialize(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(hull.Points.Select(it=>new PointF((float)it.x, (float)it.y)));
rawDetail.Outers.Add(contourHull);
}
return rawDetail;
}
///
/// 加载线数据
///
///
///
private RawDetail loadLayersDetail(string layers)
{
string[] saFullLayers = Regex.Split(layers, ",");
RawDetail rawDetail = new RawDetail();
DrawerData drawerDetail = new DrawerData();
drawerDetail.OpenFile(mapFile);
// 遍历每一个图层
foreach (string layer in saFullLayers)
{
string curveData = string.Empty;
int nCount = drawerDetail.LayerGetCurves(layer, ref curveData, false);
if (nCount == 0)
{
continue;
}
DrawerElementHelp elementHelp = new DrawerElementHelp();
List propertys = elementHelp.DeserializeList(curveData);
// 生成每一条线
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 points = new List();
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 });
}
}
}
}
drawerDetail.Dispose();
drawerDetail = null;
return rawDetail;
}
///
/// 从文件加载线数据
///
///
///
private RawDetail loadDetail(string dataFile)
{
// 从文件加载边界
RawDetail detail = new RawDetail();
using (StreamReader sr = new StreamReader(dataFile, Encoding.Default))
{
while (!sr.EndOfStream)
{
string strLine = sr.ReadLine();
if (string.IsNullOrEmpty(strLine))
{
continue;
}
if (strLine.StartsWith("Pline", StringComparison.OrdinalIgnoreCase))
{
List points = new List();
while (!sr.EndOfStream)
{
strLine = sr.ReadLine();
if (string.IsNullOrEmpty(strLine))
{
detail.Outers.Add(new LocalContour() { Points = points });
break; ;
}
string[] saLine = strLine.Split(',');
if (saLine.Length > 1)
{
points.Add(new PointF(float.Parse(saLine[0]), float.Parse(saLine[1])));
}
}
}
}
}
return detail;
}
private void Form1_Load(object sender, EventArgs e)
{
Application.Idle += application_Idle;
this.splitContainer2.FixedPanel = FixedPanel.Panel1;
}
private void application_Idle(object sender, EventArgs e)
{
CaculateStatus status = this.caculator.Status;
switch (status)
{
case CaculateStatus.None:
this.btnPlay.Enabled = true;
this.btnPause.Enabled = false;
this.btnStop.Enabled = false;
this.btnOutput.Enabled = false;
this.btnPause.Text = "暂停";
this.btnStop.Text = "停止";
break;
case CaculateStatus.Pausing:
this.btnPlay.Enabled = false;
this.btnPause.Enabled = false;
this.btnStop.Enabled = false;
this.btnOutput.Enabled = false;
this.btnPause.Text = "等待暂停";
this.btnStop.Text = "停止";
break;
case CaculateStatus.Paused:
this.btnPlay.Enabled = false;
this.btnPause.Enabled = true;
this.btnStop.Enabled = true;
this.btnOutput.Enabled = true;
this.btnPause.Text = "继续";
this.btnStop.Text = "停止";
break;
case CaculateStatus.Stopping:
this.btnPlay.Enabled = false;
this.btnPause.Enabled = false;
this.btnStop.Enabled = false;
this.btnOutput.Enabled = false;
this.btnPause.Text = "暂停";
this.btnStop.Text = "等待停止";
break;
case CaculateStatus.Stopped:
this.btnPlay.Enabled = true;
this.btnPause.Enabled = false;
this.btnStop.Enabled = false;
this.btnOutput.Enabled = true;
this.btnPause.Text = "暂停";
this.btnStop.Text = "停止";
break;
case CaculateStatus.Working:
this.btnPlay.Enabled = false;
this.btnPause.Enabled = true;
this.btnStop.Enabled = true;
this.btnOutput.Enabled = false;
this.btnPause.Text = "暂停";
this.btnStop.Text = "停止";
break;
default: break;
}
//(status == CaculateStatus.None || status == CaculateStatus.Stopped)
//{
// this.btnPlay.Enabled = true;
//}
//if (this.btnStop.Text == "等待停止")
//{
// this.btnPlay.Enabled = false;
//}
//else
//{
// this.btnPlay.Enabled = this.stop;
//}
//this.btnOutput.Enabled = (this.stop||this.btnPause.Text == "继续")
// && (nest != null && nest.PlacedPartsCount > 0)&& this.btnStop.Text!="等待停止";
//this.btnStop.Enabled = !this.stop;
//if(this.stop)
//{
// this.btnPause.Enabled = false;
//}
//txtRotationTimes.Enabled = this.rdbRotationTimes.Checked;
//this.txtAngleStart.Enabled = this.rdbRotationTimes.Checked;
//this.txtAngleEnd.Enabled = this.rdbRotationTimes.Checked;
//txtRotationAngles.Enabled = this.rdbRotationAngles.Checked;
}
private double CaculateLineLength(PathD path)
{
if(path.Count<2) return 0;
double dTotal = 0;
Clipper2Lib.PointD ptLast = path[0];
for(int i=1; i