using MECF.Framework.UI.Core.DxfScript; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Media; using System.Windows; using System.Globalization; using System.Windows.Controls; using Newtonsoft.Json.Linq; using System.Xml.Linq; using Microsoft.Win32.SafeHandles; using System.Windows.Input; using MECF.Framework.UI.Core.DxfScript.Converter; using SciChart.Core.Extensions; namespace MECF.Framework.UI.Core.DxfScript { /// /// 名称:Draw类 /// 用途:根据自定义对象画页面元素 /// public partial class GasDxfDocument { //画全部元素 public void Draw() { if (Lines.Count == 0) { return; } draw.ClearDrawing(); CreateGraphics(); InitScale(); foreach (var line in Lines) { DrawLine(line, false); } foreach (GasCircle circle in Circles) { DrawCircle(circle, false); } foreach (GasFunnel funnel in Funnels) { DrawFunnel(funnel, false); } foreach (GasText text in Texts) { DrawText(text, false); } foreach (GasPolyLine polyLine in PolyLines) { DrawPolyLine(polyLine, false); } foreach (GasAITValve valve in Valves) { DrawValve(valve, false); } foreach (GasButton button in Buttons) { DrawButton(button, false); } foreach (GasAnalogControl4Jet analog in Analogs) { DrawAnalog(analog, false); } CloseGraphics(); draw.SaveDrawing(); } //清除所有元素 private void ClearDxf() { if (Lines != null) { Lines.Clear(); } else { Lines = new List(); } if (PolyLines != null) { PolyLines.Clear(); } else { PolyLines = new List(); } if (Circles != null) { Circles.Clear(); } else { Circles = new List(); } if (Funnels != null) { Funnels.Clear(); } else { Funnels = new List(); } if (Texts != null) { Texts.Clear(); } else { Texts = new List(); } if (Valves != null) { Valves.Clear(); } else { Valves = new List(); } if (Buttons != null) { Buttons.Clear(); } else { Buttons = new List(); } if (Analogs != null) { Analogs.Clear(); } else { Analogs = new List(); } DxfWidth = 0; DxfHeight = 0; MinX = 100000; MinY = 100000; MaxX = 0; MaxY = 0; Scale = 1; dragX = 0; dragY = 0; } //开始画元素 public void DrawShape(GasBaseShape shape, bool isSelected) { CreateGraphics(); draw.LoadDrawing(dragX, dragY); if (shape is GasFunnel) { DrawFunnel(shape as GasFunnel, isSelected); } if (shape is GasLine) { DrawLine(shape as GasLine, isSelected); } else if (shape is GasCircle) { DrawCircle(shape as GasCircle, isSelected); } else if (shape is GasText) { DrawText(shape as GasText, isSelected); } else if (shape is GasPolyLine) { DrawPolyLine(shape as GasPolyLine, isSelected); } else if (shape is GasAITValve) { DrawValve(shape as GasAITValve, isSelected); } else if (shape is GasButton) { DrawButton(shape as GasButton, isSelected); } else if (shape is GasAnalogControl4Jet) { DrawAnalog(shape as GasAnalogControl4Jet, isSelected); } CloseGraphics(); } //设置画笔颜色 private Brush GetGasShapeBrush(GasBaseShape shape, bool isSelected) { if (shape == null) return NormalBrush; if (!IsExecuted) { return GetDevelopmentBrush(shape, isSelected); } else { return GetExecutionBrush(shape); } } private Pen GetPenByBrush(Brush brush) { if (brush == NormalBrush) { return NormalPen; } else if (brush == SelectedBrush) { return SelectedPen; } else if (brush == WithConditionBrush) { return WithConditionPen; } else if (brush == ReturnTrueBrush) { return ReturnTruePen; } else if (brush == WithErrorBrush) { return WithErrorPen; } else if (brush == TransparentBrush) { return TransparentPen; } else { return null; } } //画单线 private void DrawLine(GasLine line, bool isSelected, Brush brush = null) { if (brush == null) brush = GetGasShapeBrush(line, isSelected); Pen pen = GetPenByBrush(brush); double x1 = line.X1 * rate * Scale + XSPACE + dragX; double x2 = line.X2 * rate * Scale + XSPACE + dragX; double y1 = (DxfHeight - line.Y1) * rate * Scale + YSPACE + dragY; double y2 = (DxfHeight - line.Y2) * rate * Scale + YSPACE + dragY; dc.DrawLine(pen, new Point(x1, y1), new Point(x2, y2)); } //画漏斗 private void DrawFunnel(GasFunnel funnel, bool isSelected, Brush brush = null) { if (funnel == null) return; foreach (var line in funnel.GasLines) { DrawLine(line, isSelected, brush); } } //画圆 private void DrawCircle(GasCircle circle, bool isSelected, Brush brush = null) { if (brush == null) brush = GetGasShapeBrush(circle, isSelected); ; Pen pen = GetPenByBrush(brush); if (brush == NormalBrush) { pen = NormalPen; brush = TransparentBrush; } else { pen = NormalPen; //brush不变 } double x = (circle.X) * rate * Scale + XSPACE + dragX;//圆心x double y = (DxfHeight - circle.Y) * rate * Scale + YSPACE + dragY;//圆心y double r = circle.R * rate * Scale; if (circle.StartAngle > 0) { DrawGeometry(circle, isSelected, brush); } else { dc.DrawEllipse(brush, pen, new Point(x, y), r, r); } } //画弧线 public void DrawGeometry(GasCircle circle, bool isSelected, Brush brush = null) { if (brush == null) brush = GetGasShapeBrush(circle, isSelected); ; Pen pen = GetPenByBrush(brush); if (brush == NormalBrush) { pen = NormalPen; brush = TransparentBrush; } else { pen = NormalPen; //brush不变 } double x = (circle.X) * rate * Scale + XSPACE + dragX;//圆心x double y = (DxfHeight - circle.Y) * rate * Scale + YSPACE + dragY;//圆心y double r = circle.R * rate * Scale; Rect arcRect = new Rect(x - r, y - r, 2 * r, 2 * r); // 定义圆弧的起始角度和扫过角度 double startAngle = circle.StartAngle; // 起始角度 double sweepAngle = circle.EndAngle - circle.StartAngle; // 扫过角度 // 将角度转换为弧度 double startAngleRad = startAngle * Math.PI / 180; double sweepAngleRad = sweepAngle * Math.PI / 180; // 计算起始点和结束点 Point startPoint = new Point( arcRect.X + arcRect.Width / 2 + arcRect.Width / 2 * Math.Cos(startAngleRad), arcRect.Y + arcRect.Height / 2 - arcRect.Height / 2 * Math.Sin(startAngleRad)); Point endPoint = new Point( arcRect.X + arcRect.Width / 2 + arcRect.Width / 2 * Math.Cos(startAngleRad + sweepAngleRad), arcRect.Y + arcRect.Height / 2 - arcRect.Height / 2 * Math.Sin(startAngleRad + sweepAngleRad)); // 定义弧形段 ArcSegment arcSegment = new ArcSegment { Point = endPoint, Size = new Size(arcRect.Width / 2, arcRect.Height / 2), RotationAngle = 0, IsLargeArc = (sweepAngle - startAngle) > 180, SweepDirection = SweepDirection.Counterclockwise }; // 定义路径段 PathFigure pathFigure = new PathFigure { StartPoint = startPoint, Segments = new PathSegmentCollection { arcSegment } }; // 定义路径几何 PathGeometry pathGeometry = new PathGeometry(); pathGeometry.Figures.Add(pathFigure); // 使用 DrawingContext 绘制路径 dc.DrawGeometry(brush, pen, pathGeometry); } //画文本 private void DrawText(GasText text, bool isSelected, Brush brush = null) { if (brush == null) brush = GetGasShapeBrush(text, isSelected); ; Pen pen = GetPenByBrush(brush); if (string.IsNullOrEmpty(text.Text)) return; string[] textLines = Regex.Split(text.Text, "\\\\P"); for (int i = 0; i < textLines.Length; i++) { double x = text.X; double y = text.Y; double rectWidth = text.RectWidth; double rectHeight = text.RectHeight; double textWidth = GetFontWidth(textLines[i], text.FontSize); double textHeight = text.FontSize; double fontSize = text.FontSize; int alignment = text.Alignment; double lineSpace = text.LineSpace; switch (alignment) { case 1: x += (rectWidth - textWidth) / 2; y = y - (rectHeight - textHeight) / 2; y -= (textHeight + lineSpace) * i; break; case 4: x += (rectWidth - textWidth) / 2; y += textHeight / 2; y -= (textHeight + lineSpace) * i; break; case 7: x += (rectWidth - textWidth) / 2; y += (rectHeight + textHeight) / 2; y -= (textHeight + lineSpace) * i; break; case 2: x -= textWidth / 2; y = y - (rectHeight - textHeight) / 2; y -= (textHeight + lineSpace) * i; break; case 5: x -= textWidth / 2; y += textHeight / 2; y -= (textHeight + lineSpace) * i; break; case 8: x -= textWidth / 2; y += (rectHeight + textHeight) / 2; y -= (textHeight + lineSpace) * i; break; case 3: x -= (rectWidth + textWidth) / 2; y = y - (rectHeight - textHeight) / 2; y -= (textHeight + lineSpace) * i; break; case 6: x -= (rectWidth + textWidth) / 2; y += textHeight / 2; y -= (textHeight + lineSpace) * i; break; case 9: x -= (rectWidth + textWidth) / 2; y += (rectHeight + textHeight) / 2; y -= (textHeight + lineSpace) * i; break; } x = x * rate * Scale + XSPACE + dragX; y = (DxfHeight - y) * rate * Scale + YSPACE + dragY; dc.DrawText(GetFormattedText(textLines[i], text.FontSize * rate * Scale, brush), new Point(x, y)); } } //画多线 private void DrawPolyLine(GasPolyLine polyLine, bool isSelected, Brush brush = null) { if (brush == null) brush = GetGasShapeBrush(polyLine, isSelected); ; Pen pen = GetPenByBrush(brush); foreach (GasLine line in polyLine.InnerLines) { DrawLine(line, isSelected, brush); } } //画按钮 private void DrawButton(GasButton button, bool isSelected, Brush brush = null) { if (brush == null) brush = GetGasShapeBrush(button, isSelected); ; Pen pen = GetPenByBrush(brush); if (brush == NormalBrush) { pen = NormalPen; brush = TransparentBrush; } else { pen = NormalPen; } double x, y, width, height; x = Math.Min(button.InnerPolyLine.InnerLines[0].X1, button.InnerPolyLine.InnerLines[0].X2); y = Math.Max(button.InnerPolyLine.InnerLines[0].Y1, button.InnerPolyLine.InnerLines[0].Y2); width = Math.Abs(button.InnerPolyLine.InnerLines[0].X1 - button.InnerPolyLine.InnerLines[0].X2); height = Math.Abs(button.InnerPolyLine.InnerLines[1].Y1 - button.InnerPolyLine.InnerLines[1].Y2); x = x * rate * Scale + XSPACE + dragX; y = (DxfHeight - y) * rate * Scale + YSPACE + dragY; width = width * rate * Scale; height = height * rate * Scale; dc.DrawRectangle(brush, pen, new Rect(x, y, width, height)); DrawText(button.InnerText, isSelected, NormalBrush); } //画阀 private void DrawValve(GasAITValve valve, bool isSelected, Brush brush = null) { if (brush == null) brush = GetGasShapeBrush(valve, isSelected); ; Pen pen = GetPenByBrush(brush); DrawCircle(valve.InnerCircle, isSelected, brush); DrawText(valve.InnerText, isSelected, NormalBrush); if (valve.InnerPolyLine != null && valve.InnerPolyLine.InnerLines != null) { DrawPolyLine(valve.InnerPolyLine, isSelected, NormalBrush); } } //画按钮 private void DrawAnalog(GasAnalogControl4Jet analog, bool isSelected, Brush brush = null) { if (brush == null) brush = GetGasShapeBrush(analog, isSelected); ; Pen pen = GetPenByBrush(brush); DrawButton(analog.TopButton, isSelected, brush); DrawButton(analog.LeftButton, isSelected, brush); DrawButton(analog.RightButton, isSelected, brush); } //创建自定义画布对象 private void CreateGraphics() { if (dc == null) dc = draw.CreateGraphics(); } //清除画布对象 private void CloseGraphics() { if (dc != null) { draw.Dispose(); } dc = null; } private double GetFontWidth(string text, double fontSize) { if (computeSizeTextBlock == null) { computeSizeTextBlock = new TextBlock(); PixelsPerDip = DpiHelper.GetPixelsPerDip(Application.Current.MainWindow); } computeSizeTextBlock.Text = text; computeSizeTextBlock.FontSize = fontSize == 0 ? 15 : fontSize; computeSizeTextBlock.FontFamily = new FontFamily("宋体"); FormattedText formattedText = new FormattedText( computeSizeTextBlock.Text, CultureInfo.GetCultureInfo("zh-CN"), FlowDirection.LeftToRight, new Typeface(computeSizeTextBlock.FontFamily, computeSizeTextBlock.FontStyle, computeSizeTextBlock.FontWeight, computeSizeTextBlock.FontStretch), computeSizeTextBlock.FontSize, Brushes.Black); return formattedText.Width; } private FormattedText GetFormattedText(string text, double fontSize, Brush brush) { if (computeSizeTextBlock == null) { computeSizeTextBlock = new TextBlock(); } computeSizeTextBlock.Text = text; computeSizeTextBlock.FontSize = fontSize == 0 ? 15 : fontSize; computeSizeTextBlock.FontFamily = new FontFamily("宋体"); FormattedText formattedText = new FormattedText( computeSizeTextBlock.Text, CultureInfo.GetCultureInfo("zh-CN"), FlowDirection.LeftToRight, new Typeface(computeSizeTextBlock.FontFamily, computeSizeTextBlock.FontStyle, computeSizeTextBlock.FontWeight, computeSizeTextBlock.FontStretch), computeSizeTextBlock.FontSize, brush); return formattedText; } #region 根据不同环境对画刷处理 //主方法 GetGasShapeBrush:根据 IsExecuted 的状态分为开发态和执行态处理。 //开发态处理 GetDevelopmentBrush:处理开发态下的逻辑,包括条件检查和选择画刷。 //如果形状未启用,直接返回 DisabledBrush。 //依次检查 BoolCondition 和 StringCondition,如果有错误,直接返回 WithErrorBrush。 //处理特定类型的形状逻辑。 //条件检查 CheckAndHandleCondition:统一处理 BoolCondition 和 StringCondition 的检查逻辑,减少代码重复。 //执行态处理 GetExecutionBrush:处理执行态下的逻辑,包括条件执行和选择画刷。 //如果形状未启用,直接返回 DisabledBrush。 //依次执行 BoolCondition 和 StringCondition,如果有错误,直接返回 WithErrorBrush。 //条件执行 ExecuteAndHandleCondition:统一处理 BoolCondition 和 StringCondition 的执行逻辑,减少代码重复。 //处理开发环境下的特定形状 HandleSpecialShapesDevelopment:处理开发环境下特定形状的逻辑。 //处理执行环境下的特定形状 HandleSpecialShapesExecution:处理执行环境下特定形状的逻辑。 private Brush GetDevelopmentBrush(GasBaseShape shape, bool isSelected) { if (isSelected) return SelectedBrush; if (!shape.Enable) return DisabledBrush; Brush brush = NormalBrush; brush = CheckAndHandleCondition(shape.BoolCondition, brush, shape.Id, BoolConditions); if (brush == WithErrorBrush) return brush; brush = CheckAndHandleCondition(shape.StringCondition, brush, shape.Id, StringConditions); if (brush == WithErrorBrush) return brush; brush = CheckAndHandleCondition(shape.ClickCondition, brush, shape.Id, ClickConditions); if (brush == WithErrorBrush) return brush; brush = HandleSpecialShapesDevelopment(shape, brush); return brush; } private Brush HandleSpecialShapesDevelopment(GasBaseShape shape, Brush currentBrush) { if (shape is GasAITValve) { // 处理 GasAITValve 的开发环境逻辑 return currentBrush; } else if (shape is GasAnalogControl4Jet) { // 处理 GasAnalogControl4Jet 的开发环境逻辑 return currentBrush; } return currentBrush; } private Brush CheckAndHandleCondition(Script condition, Brush currentBrush, int shapeId, Dictionary conditionsDict) { if (condition == null || condition.Result == ScriptResult.EMPTY) { return currentBrush; } else if (condition.Result == ScriptResult.SUCCESS) { return WithConditionBrush; } else if (condition.Result == ScriptResult.ERROR) { if (conditionsDict.ContainsKey(shapeId)) { if (!conditionsDict[shapeId].EndsWith("TODO")) { conditionsDict[shapeId] += "\n//" + condition.Error + ":TODO"; } } return WithErrorBrush; } return currentBrush; } private Brush GetExecutionBrush(GasBaseShape shape) { bool isExec = shape.ClickCondition == null && shape.BoolCondition == null && shape.StringCondition == null; if (!shape.Enable&& isExec) { return DisabledBrush; } Brush brush = NormalBrush; brush = ExecuteAndHandleCondition(shape.ClickCondition, brush, shape); brush = ExecuteAndHandleCondition(shape.BoolCondition, brush, shape); if (brush == WithErrorBrush) return brush; brush = ExecuteAndHandleCondition(shape.StringCondition, brush, shape); if (brush == WithErrorBrush) return brush; return brush; } private Brush ExecuteAndHandleCondition(Script condition, Brush currentBrush, GasBaseShape shape) { if (condition == null) return currentBrush; if (condition.Result == ScriptResult.EMPTY) { return currentBrush; } //由于一直在Draw(),会不断的执行脚本 导致十分卡顿 //而且由于采用切换key的方法读取值,所以这部分不需要一直执行脚本 //if (isExecute) //{ // condition.Execute(); //} if (condition.Result == ScriptResult.SUCCESS) { return HandleSpecialShapes(condition, currentBrush, shape); } else if (condition.Result == ScriptResult.ERROR) { // return WithErrorBrush; return NormalBrush; } return currentBrush; } private Brush HandleSpecialShapes(Script condition, Brush currentBrush, GasBaseShape shape) { // 提取重复的逻辑到一个方法 Brush defaultBrush = GetDefaultBrush(shape, currentBrush); switch (shape) { case GasAITValve aiTValve: var result = condition.ReadValue(aiTValve.Key); return result ? ReturnTrueBrush : defaultBrush; case GasAnalogControl4Jet mfc: var value = condition.ReadValue(mfc.ValueKey); mfc.LeftButton.InnerText.Text = value.ToString("f2"); mfc.RightButton.InnerText.Text = condition.ReadValue(mfc.UnitKey); return value>0?GasMapProvider.ChangeMFCColor:defaultBrush; case GasButton btn: return condition.ReadValue(btn.DataKey) ? ReturnTrueBrush : defaultBrush; case GasCircle cycle: return !string.IsNullOrEmpty(cycle.Key) && condition.ReadValue(cycle.Key) ? ReturnTrueBrush : defaultBrush; default: return defaultBrush; } } private Brush GetDefaultBrush(GasBaseShape shape, Brush currentBrush) { // 如果 shape 自身有 Brush,则使用它;否则,使用传入的 currentBrush return shape.Brush ?? currentBrush; } #endregion } }