GasDxfDocument.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /**
  2. *
  3. * @author seagle
  4. * @date 2024-7-22
  5. * @Description 管路图处理主对象封装
  6. */
  7. using Aitex.Common.Util;
  8. using Aitex.Core.RT.DataCenter;
  9. using MECF.Framework.Common.DataCenter;
  10. using netDxf;
  11. using netDxf.Entities;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Configuration;
  15. using System.Globalization;
  16. using System.IO;
  17. using System.Linq;
  18. using System.Text.RegularExpressions;
  19. using System.Windows;
  20. using System.Windows.Controls;
  21. using System.Windows.Input;
  22. using System.Windows.Media;
  23. using System.Xml;
  24. using Point = System.Windows.Point;
  25. namespace MECF.Framework.UI.Core.DxfScript
  26. {
  27. /// <summary>
  28. /// 名称:入口类
  29. /// 用途:dxf文件信息加载
  30. /// </summary>
  31. [Serializable]
  32. public partial class GasDxfDocument
  33. {
  34. //原始图形
  35. public List<GasLine> Lines = null;
  36. public List<GasCircle> Circles = null;
  37. public List<GasFunnel> Funnels = null;
  38. public List<GasText> Texts = null;
  39. public List<GasPolyLine> PolyLines = null;
  40. public List<GasAITValve> Valves = null;
  41. public List<GasButton> Buttons = null;
  42. public List<GasAnalogControl4Jet> Analogs = null;
  43. //事件属性
  44. public Dictionary<int, string> BoolConditions { get; set; } = null;
  45. public Dictionary<int, string> StringConditions { get; set; } = null;
  46. public Dictionary<int, string> ClickConditions { get; set; } = null;
  47. public string InitScriptContent { get; set; } = null;
  48. public Script InitScriptExpress { get; set; } = null;
  49. public double DxfWidth { get; set; } = 0;
  50. public double DxfHeight { get; set; } = 0;
  51. public double MinX { get; set; } = 100000;
  52. public double MinY { get; set; } = 100000;
  53. public double MaxX { get; set; } = 0;
  54. public double MaxY { get; set; } = 0;
  55. //编辑属性
  56. public string GasFilename { get; set; } = null;
  57. public bool IsGasFileModified { get; set; } = false;
  58. public GasBaseShape SelectedShape = null;
  59. public bool IsExecuted { get; set; } = false;
  60. public DrawingCanvas draw { get; set; } = null;
  61. public Brush NormalBrush = new SolidColorBrush(Colors.Black);
  62. public Brush SelectedBrush = new SolidColorBrush(Colors.Red);
  63. public Brush WithConditionBrush = new SolidColorBrush(Colors.LightBlue);
  64. public Brush ReturnTrueBrush = new SolidColorBrush(Colors.Green);
  65. public Brush WithErrorBrush = new SolidColorBrush(Colors.Yellow);
  66. public Brush TransparentBrush = new SolidColorBrush(Colors.Transparent);
  67. public Brush DisabledBrush = new SolidColorBrush(Colors.Gray);
  68. public Pen NormalPen, SelectedPen, WithConditionPen, ReturnTruePen, WithErrorPen, TransparentPen, DisabledPen;//,BackgroundPen;
  69. public static Dictionary<Brush, Pen> BrushPenMapping;
  70. public DrawingContext dc = null;
  71. public double LineWidth = 1;
  72. private static TextBlock computeSizeTextBlock = null;
  73. public static double PixelsPerDip;
  74. public GasDxfDocument(DrawingCanvas canvas, bool isExecute, string fileName)
  75. {
  76. ClearAll();
  77. var path = QueryDataClient.Instance.Service.PollData(new List<string>() { "GasUIConfigHome" }).FirstOrDefault().Value.ToString();
  78. if (path == null)
  79. {
  80. MessageBox.Show($"\"{path} is not set!");
  81. return;
  82. }
  83. GasFilename = path + fileName;
  84. draw = canvas;
  85. NormalBrush.Freeze();
  86. SelectedBrush.Freeze();
  87. WithConditionBrush.Freeze();
  88. ReturnTrueBrush.Freeze();
  89. WithErrorBrush.Freeze();
  90. TransparentBrush.Freeze();
  91. DisabledBrush.Freeze();
  92. IsExecuted = isExecute;
  93. NormalPen = new Pen(NormalBrush, LineWidth);
  94. NormalPen.Freeze();//可以提高性能
  95. SelectedPen = new Pen(SelectedBrush, LineWidth);
  96. SelectedPen.Freeze();//可以提高性能
  97. WithConditionPen = new Pen(WithConditionBrush, LineWidth);
  98. WithConditionPen.Freeze();//可以提高性能
  99. ReturnTruePen = new Pen(ReturnTrueBrush, LineWidth);
  100. ReturnTruePen.Freeze();//可以提高性能
  101. WithErrorPen = new Pen(WithErrorBrush, LineWidth);
  102. WithErrorPen.Freeze();//可以提高性能
  103. TransparentPen = new Pen(TransparentBrush, LineWidth);
  104. TransparentPen.Freeze();//可以提高性能
  105. DisabledPen = new Pen(DisabledBrush, LineWidth);
  106. DisabledPen.Freeze();//可以提高性能
  107. //BackgroundPen = new Pen(BackgroundBrush, LineWidth);
  108. }
  109. /// <summary>
  110. /// 读取dxf文件数据 转化为页面元素 加载元素事件
  111. /// </summary>
  112. /// <param name="filename"></param>
  113. public void LoadDxf(string filename)
  114. {
  115. #region 清除页面组件元素 准备重新加载dxf
  116. ClearDxf();
  117. #endregion
  118. #region 文件流方式进行识别dxf信息 并转化为自定义元素组件
  119. StreamReader reader = new StreamReader(filename);
  120. DxfRecord record = new DxfRecord();
  121. while (ReadOneRecord(reader, ref record))
  122. {
  123. if (record.Code == 0 && record.Value.Equals("EOF"))
  124. {
  125. break;
  126. }
  127. if (record.Code == 100 && record.Value.Equals("AcDbLine")) ReadOneAcDbLine(reader);
  128. else if (record.Code == 100 && record.Value.Equals("AcDbCircle")) ReadOneAcDbCircle(reader);
  129. else if (record.Code == 100 && record.Value.Equals("AcDbText_Nouse")) ReadOneAcDbTextNouse(reader);
  130. else if (record.Code == 100 && record.Value.Equals("AcDbMText")) ReadOneAcDbMText(reader);
  131. else if (record.Code == 100 && record.Value.Equals("AcDbPolyline")) ReadOneAcDbPolyline(reader);
  132. }
  133. RecognizeShape();
  134. #endregion
  135. #region netDxf 方式识别dxf信息 并转化为自定义元素组件
  136. NetDxfDocument(filename);
  137. #endregion
  138. reader.Close();
  139. IsGasFileModified = true;
  140. //不再对dxf做坐标变换,只是取第一象限
  141. DxfWidth = MaxX;
  142. DxfHeight = MaxY;
  143. }
  144. #region 文件流读取dxf格式信息
  145. /*从文件流中读取一条记录*/
  146. private bool ReadOneRecord(StreamReader reader, ref DxfRecord record)
  147. {
  148. string line = reader.ReadLine();
  149. if (line == null) return false;
  150. /*
  151. if (line.Equals("") || !line.Substring(0, 1).Equals(" "))
  152. {
  153. MessageBox.Show("Line must begin with a space["+line+"]", "Notice", MessageBoxButton.OK);
  154. Clear();
  155. return false;
  156. }
  157. */
  158. line = line.Trim();
  159. record.Code = int.Parse(line);
  160. record.Value = reader.ReadLine();
  161. if (record.Value == null) return false;
  162. return true;
  163. }
  164. private void ReadOneAcDbPolyline(StreamReader reader)
  165. {
  166. List<(double, double)> points = new List<(double, double)>();
  167. DxfRecord recordDetail = new DxfRecord();
  168. double x, y;
  169. x = y = 0;
  170. bool failed = false;
  171. while (ReadOneRecord(reader, ref recordDetail))
  172. {
  173. if (recordDetail.Code == 10)
  174. {
  175. x = double.Parse(recordDetail.Value);
  176. }
  177. if (recordDetail.Code == 20)
  178. {
  179. y = double.Parse(recordDetail.Value);
  180. if (x <= GasBaseShape.E || y <= GasBaseShape.E)
  181. {
  182. failed = true;
  183. break;
  184. }
  185. if (x > MaxX)
  186. {
  187. MaxX = x;
  188. }
  189. if (x < MinX)
  190. {
  191. MinX = x;
  192. }
  193. if (y > MaxY)
  194. {
  195. MaxY = y;
  196. }
  197. if (y < MinY)
  198. {
  199. MinY = y;
  200. }
  201. points.Add((x, y));
  202. }
  203. if (recordDetail.Code == 0) break;
  204. }
  205. if (failed) return;
  206. GasPolyLine polyLine = new GasPolyLine();
  207. for (int i = 0; i < points.Count; i++)
  208. {
  209. polyLine.InnerLines.Add(new GasLine(points[i].Item1, points[i].Item2, points[(i + 1) % points.Count].Item1, points[(i + 1) % points.Count].Item2));
  210. }
  211. PolyLines.Add(polyLine);
  212. polyLine.Id = polyLine.CreateId();
  213. }
  214. private void ReadOneAcDbMText(StreamReader reader)
  215. {
  216. double x, y;
  217. string text;
  218. x = y = 0;
  219. double x2, y2;
  220. x2 = y2 = 0;
  221. text = "";
  222. DxfRecord recordDetail = new DxfRecord();
  223. int align71 = 0;//1 = 左上;2 = 中上;3 = 右上 4 = 左中;5 = 正中;6 = 右中 7 = 左下;8 = 中下;9 = 右下
  224. double space44 = 0.6;
  225. double fontSize = 0;
  226. double rectWidth = 0;
  227. double rectHeight = 0;
  228. double textHeight = 0;
  229. while (ReadOneRecord(reader, ref recordDetail))
  230. {
  231. if (recordDetail.Code == 10) x = double.Parse(recordDetail.Value);
  232. if (recordDetail.Code == 20) y = double.Parse(recordDetail.Value);
  233. if (recordDetail.Code == 11) x2 = double.Parse(recordDetail.Value);
  234. if (recordDetail.Code == 21) y2 = double.Parse(recordDetail.Value);
  235. if (recordDetail.Code == 1) text = recordDetail.Value;
  236. if (recordDetail.Code == 71) align71 = int.Parse(recordDetail.Value);
  237. if (recordDetail.Code == 40) fontSize = double.Parse(recordDetail.Value);
  238. if (recordDetail.Code == 41) rectWidth = double.Parse(recordDetail.Value);
  239. if (recordDetail.Code == 44) space44 = double.Parse(recordDetail.Value);
  240. if (recordDetail.Code == 46) rectHeight = double.Parse(recordDetail.Value);
  241. if (recordDetail.Code == 0) break;
  242. }
  243. if (x <= GasBaseShape.E || y <= GasBaseShape.E) return;
  244. if (text != null)
  245. {
  246. string[] fields = text.Split(';');
  247. if (fields.Length > 0) text = fields[fields.Length - 1];
  248. if (fields.Length > 1)
  249. {
  250. for (int fieldId = 0; fieldId < fields.Length - 1; fieldId++)
  251. {
  252. string wstr = fields[fieldId];
  253. if (wstr.Contains("\\W"))
  254. {
  255. double fontRate = double.Parse(wstr.Substring(2, wstr.Length - 2));
  256. fontSize *= fontRate;
  257. break;
  258. }
  259. }
  260. List<string> hText = new List<string>();
  261. foreach (var wstr in fields)
  262. {
  263. if (wstr.Contains("\\H"))
  264. {
  265. var content = wstr.Split('\\').FirstOrDefault();
  266. if (string.IsNullOrEmpty(content)) continue;
  267. hText.Add(content);
  268. }
  269. }
  270. hText.Add(text);
  271. text = string.Join("", hText.ToArray());
  272. }
  273. if (text != null && text.Length > 0)
  274. {
  275. text = text.Substring(0, text.Length - 1);
  276. Texts.Add(new GasText(x, y, text));
  277. //SET:fontSize-字符尺寸
  278. //SET:align71-对齐方式
  279. //SET:space44-行间距
  280. //SET:rectWidth-矩形宽度
  281. //SET:rectHeight-矩形高度
  282. string[] textLines = Regex.Split(text, "\\\\P");
  283. if (textLines.Length > 0)
  284. {
  285. //SET:textHeight-文本高度
  286. textHeight = fontSize * textLines.Length - space44 * rectHeight;
  287. }
  288. //根据对齐调整位置
  289. GasText obj = Texts[Texts.Count - 1];
  290. obj.RectWidth = rectWidth;
  291. obj.RectHeight = rectHeight;
  292. obj.LineSpace = space44;
  293. obj.FontSize = fontSize;
  294. obj.Alignment = align71;
  295. if (obj.X < MinX) MinX = obj.X;
  296. if (obj.Y < MinY) MinY = obj.Y;
  297. if (obj.X + obj.RectWidth > MaxX) MaxX = obj.X + obj.RectWidth;
  298. if (obj.Y + obj.RectHeight > MaxY) MaxY = obj.Y + obj.RectHeight;
  299. }
  300. }
  301. }
  302. private void ReadOneAcDbTextNouse(StreamReader reader)
  303. {
  304. double x, y;
  305. string text;
  306. x = y = 0;
  307. text = "";
  308. DxfRecord recordDetail = new DxfRecord();
  309. while (ReadOneRecord(reader, ref recordDetail))
  310. {
  311. if (recordDetail.Code == 10) x = double.Parse(recordDetail.Value);
  312. if (recordDetail.Code == 20) y = double.Parse(recordDetail.Value);
  313. if (recordDetail.Code == 1) text = recordDetail.Value;
  314. if (recordDetail.Code == 0) break;
  315. }
  316. if (x < 0 || y < 0) return;
  317. Texts.Add(new GasText(x, y, text));
  318. }
  319. private void ReadOneAcDbCircle(StreamReader reader)
  320. {
  321. double x, y, r, startAngle, endAngle;
  322. x = y = r = startAngle = endAngle = 0;
  323. DxfRecord recordDetail = new DxfRecord();
  324. while (ReadOneRecord(reader, ref recordDetail))
  325. {
  326. if (recordDetail.Code == 10) x = double.Parse(recordDetail.Value);
  327. if (recordDetail.Code == 20) y = double.Parse(recordDetail.Value);
  328. if (recordDetail.Code == 40) r = double.Parse(recordDetail.Value);
  329. if (recordDetail.Code == 50) startAngle = double.Parse(recordDetail.Value);
  330. if (recordDetail.Code == 51) endAngle = double.Parse(recordDetail.Value);
  331. if (recordDetail.Code == 0) break;
  332. }
  333. if (x <= GasBaseShape.E || y <= GasBaseShape.E) return;
  334. Circles.Add(new GasCircle(x, y, r, startAngle, endAngle));
  335. if (x + r > MaxX)
  336. {
  337. MaxX = x + r;
  338. }
  339. if (x - r < MinX)
  340. {
  341. MinX = x - r;
  342. }
  343. if (y + r > MaxY)
  344. {
  345. MaxY = y + r;
  346. }
  347. if (y - r < MinY)
  348. {
  349. MinY = y - r;
  350. }
  351. }
  352. private void ReadOneAcDbLine(StreamReader reader)
  353. {
  354. double x1, y1, x2, y2;
  355. x1 = x2 = y1 = y2 = 0;
  356. DxfRecord recordDetail = new DxfRecord();
  357. string sx1, sy1, sx2, sy2;
  358. sx1 = sx2 = sy1 = sy2 = "";
  359. while (ReadOneRecord(reader, ref recordDetail))
  360. {
  361. if (recordDetail.Code == 10)
  362. {
  363. x1 = double.Parse(recordDetail.Value);
  364. sx1 = recordDetail.Value;
  365. }
  366. if (recordDetail.Code == 20)
  367. {
  368. y1 = double.Parse(recordDetail.Value);
  369. sy1 = recordDetail.Value;
  370. }
  371. if (recordDetail.Code == 11)
  372. {
  373. x2 = double.Parse(recordDetail.Value);
  374. sx2 = recordDetail.Value;
  375. }
  376. if (recordDetail.Code == 21)
  377. {
  378. y2 = double.Parse(recordDetail.Value);
  379. sy2 = recordDetail.Value;
  380. }
  381. if (recordDetail.Code == 0) break;
  382. }
  383. if (x1 <= GasBaseShape.E || x2 <= GasBaseShape.E || y1 <= GasBaseShape.E || y2 <= GasBaseShape.E) return;
  384. GasLine gasLine = new GasLine(x1, y1, x2, y2);
  385. Lines.Add(gasLine);
  386. gasLine.Tag = sx1 + "," + sy1 + "," + sx2 + "," + sy2;
  387. if (x1 > MaxX)
  388. {
  389. MaxX = x1;
  390. }
  391. if (x1 < MinX)
  392. {
  393. MinX = x1;
  394. }
  395. if (x2 > MaxX)
  396. {
  397. MaxX = x2;
  398. }
  399. if (x2 < MinX)
  400. {
  401. MinX = x2;
  402. }
  403. if (y1 > MaxY)
  404. {
  405. MaxY = y1;
  406. }
  407. if (y1 < MinY)
  408. {
  409. MinY = y1;
  410. }
  411. if (y2 > MaxY)
  412. {
  413. MaxY = y2;
  414. }
  415. if (y2 < MinY)
  416. {
  417. MinY = y2;
  418. }
  419. }
  420. #endregion
  421. #region netDxf 读取dxf格式信息
  422. private void NetDxfDocument(string filename)
  423. {
  424. using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
  425. {
  426. // 使用 Stream 参数加载 DXF 文件
  427. DxfDocument dxf = DxfDocument.Load(filename);
  428. if (dxf != null)
  429. {
  430. RecognizeGasFunnel(dxf);
  431. }
  432. }
  433. }
  434. #endregion
  435. }
  436. class DxfRecord
  437. {
  438. public int Code { get; set; }
  439. public string Value { get; set; }
  440. }
  441. }