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 placements, double materialUtilization, long elapsedMilliseconds); // public delegate void ExportPlaceMentsEventHandler(Bitmap bmp, string info); public class CaculateHelpWeb : IDisposable { /// /// 任务唯一标识符 /// public string TaskId { get; private set; } = Guid.NewGuid().ToString(); public IterateEventHandler IterateEvent { get; set; } = null; public ExportPlaceMentsEventHandler ExportPlaceMentsEvent { get; set; } = null; /// /// web停止线程任务用 /// private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); private CountdownEvent countdown = new CountdownEvent(0); /// /// 部署文件 /// public string DeployFile { get; set; } = string.Empty; /// /// 边界图层 /// public string BorderLayer { get; set; } = string.Empty; /// /// 断层图层 /// public string FaultLayer { get; set; } = string.Empty; /// /// CoverageRate覆盖率 /// public double CoverageRate { get; set; } = 0.0; /// /// 单侧井 /// public int SingleWell { get; set; } = 0; /// /// 双侧井 /// public int DoubleWell { get; set; } = 0; /// /// 消息Id,和前端进度条通讯用 /// public string ConnectionId { get; set; } = string.Empty; /// /// 是否已经停止运算 /// public bool IsStop { get; set; } = true; /// /// 井参数 /// public WellsConfig WellParameters { get; set; } = new WellsConfig(); /// /// 计算参数 /// public CaculateConfig CaculateParameter { get; set; } = new CaculateConfig(); /// /// 显示进度事件 /// public Action 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; } } } /// /// 图片导出的宽度 /// public int ImageWidth { get; set; } = 500; /// /// 图片输出的高度 /// 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; } /// /// 保存指定文件 /// /// /// 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; // 跟踪是否已释放 /// /// 受保护的虚方法,用于释放资源 /// /// 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; } } /// /// 实现 IDisposable 接口 /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); // 防止垃圾回收器再次调用析构函数 } /// /// 暂停 /// public void Pause() { NeedStop = true; Status = CaculateStatus.Pausing; // 信号关闭阻,塞当前线程 ma.Reset(); } /// /// 继续 /// public void Continue() { NeedStop = false; if (this.Status!= CaculateStatus.Pausing && this.Status != CaculateStatus.Paused) { return; } Status = CaculateStatus.Working; // 信号打开,不阻塞当前线程 ma.Set(); } /// /// 停止 /// public void Stop() { NeedStop = true; Status = CaculateStatus.Stopping; this.IsStop = true; ma.Set(); } /// /// Web停止 /// 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("警告:计算线程仍在运行"); } } } /// /// 保存部署图 /// /// 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; } /// /// 执行计算 /// /// /// 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 shapes = new List(); 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; /// /// 生成部署图和部署信息 /// /// 方案的索引 /// 输出的部署图片 /// 输出的部署信息 /// 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; } /// /// 生成部署图和部署信息 /// /// /// /// 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 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) { 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 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; } /// /// 导出部署图 /// private void ExportPlaceMents() { if(exportPlacementImage(out Bitmap image, out string info)) { this.ExportPlaceMentsEvent?.Invoke(image, info); } } /// /// 设置进组的显示样式 /// /// 井组 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 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 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 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 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 }); } } } } return rawDetail; } private List> sourceWellGroups = new List>(); /// /// 加载井组的轮廓数据 /// /// /// private RawDetail loadWellGroupDetail(string layers) { sourceWellGroups = new List>(); 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 lstPt = new List(); string strElementData = this.drawer.GetElementByPosition(pos); DrawerElementProperty property = DrawerElementHelp.Deserialize(strElementData); //Trace.TraceInformation(strElementData); //Trace.TraceWarning(strElementData); sourceWellGroups.Add(new Tuple(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(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 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; } } // public enum CaculateStatus // { // None = 0, // Stopping =1, // Stopped = 2, // Pausing = 3, // Paused = 4, // Working =5, // } }