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
}
}