WinDrawWaterNode.xaml.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Globalization;
  5. using System.Linq;
  6. using System.Text.RegularExpressions;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using System.Windows.Data;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using SAGA.Models;
  13. namespace SAGA.GplotDrawData
  14. {
  15. /// <summary>
  16. /// WinDrawWaterNode.xaml 的交互逻辑
  17. /// </summary>
  18. public partial class WinDrawWaterNode {
  19. public WinDrawWaterNode() {
  20. InitializeComponent();
  21. Vertex.SetRadius(6, 6);
  22. this.Loaded += WinDrawWaterNode_Loaded;
  23. }
  24. private bool IsRead = true;
  25. private LogicNode m_data;
  26. public WinDrawWaterNode(LogicNode node) : this() {
  27. m_data = node;
  28. IsRead = false;
  29. }
  30. private void WinDrawWaterNode_Loaded(object sender, RoutedEventArgs e) {
  31. if (!IsRead) goto Run;
  32. var node = DbHelper.FindOneByFile<LogicNode>();
  33. m_data = node;
  34. if (m_data == null)
  35. {
  36. return;
  37. }
  38. Run:
  39. LogicNode root = new LogicNode { Name = m_data.Name };
  40. m_data.Nodes.ForEach(t => root.Nodes.Add(new LogicNode() { Name = t.Name }));
  41. this.rootNode.ItemsSource = new ObservableCollection<LogicNode> { root };
  42. var ln = m_data.Nodes.FirstOrDefault();
  43. Draw(ln);
  44. }
  45. private void Draw(LogicNode ln) {
  46. if (ln == null) return;
  47. this.panel.Children.Clear();
  48. #region 夏冻冬冷需要增加楼层节点
  49. //夏冻冬冷需要增加楼层节点
  50. if (Regex.IsMatch(ln.Name, "夏-冷冻水|冬-冷却水")) {
  51. //取出所有的冷冻水
  52. var water = DrawDataServer.GetWaterData();
  53. var floorNames = water.FloorDatas.Select(t => t.Name).ToList();
  54. LogicNode floorLogicNode = new LogicNode
  55. {
  56. RelationType = ChildrenRelationType.ParallelCon
  57. };
  58. floorNames.ForEach(name => floorLogicNode.Nodes.Add(new LogicNode() { Elements = new List<SgElement>() { new SgElement("", name) } }));
  59. if (ln.Nodes.Count == 2)//只有两个节点
  60. {
  61. var sameRealNode = ln.Nodes[1].RealNodes.FirstOrDefault(rn =>
  62. ln.Nodes[0].RealNodes[0].ToString() == rn.ToString()
  63. || ln.Nodes[0].RealNodes[1].ToString() == rn.ToString());
  64. if (sameRealNode != null) {
  65. floorLogicNode.RealNodes.Add(ln.Nodes[0].RealNodes.FirstOrDefault(rn => rn != sameRealNode));
  66. floorLogicNode.RealNodes.Add(ln.Nodes[1].RealNodes.FirstOrDefault(rn => rn != sameRealNode));
  67. ln.Nodes.Add(floorLogicNode);
  68. }
  69. }
  70. }
  71. #endregion
  72. var n = 3;
  73. var top = perHeight * (n - 1) / 2.0d;
  74. var start = new Point(30, this.panel.Width / 4.0d);
  75. var end = start;
  76. //起点
  77. this.panel.Children.Add(Vertex.GetHollow(start));
  78. //数据整理,去掉外挂
  79. // ln.Nodes.RemoveAll(t => t.RelationType == ChildrenRelationType.AddOnSystem);
  80. end = DrawNode(ln, end, top);
  81. //if (Regex.IsMatch(ln.Name, "夏-冷冻水|冬-冷却水")) {
  82. // end = end.AddX(width);
  83. // //连接终点与起点
  84. // var temp1 = start.AddY(perHeight * 4);
  85. // var temp2 = end.AddY(perHeight * 4);
  86. // this.panel.Children.Add(new SgLine(start.AddY(6), temp1));
  87. // this.panel.Children.Add(new SgLine(temp2.AddX(-6), temp1));
  88. // this.panel.Children.Add(new SgLine(end.AddX(-6), end.AddX(-width + 6)));
  89. // //终点
  90. // this.panel.Children.Add(Vertex.GetHollow(end.AddX(-width)));
  91. // this.panel.Children.Add(Vertex.GetHollow(end));
  92. // this.panel.Children.Add(Vertex.GetHollow(temp2));
  93. //}
  94. //else
  95. { //连接终点与起点
  96. var temp1 = start.AddY(perHeight * 4);
  97. var temp2 = end.AddY(perHeight * 4);
  98. this.panel.Children.Add(new SgLine(start.AddY(+6), temp1));
  99. this.panel.Children.Add(new SgLine(temp2, temp1));
  100. this.panel.Children.Add(new SgLine(end.AddY(+6), temp2));
  101. //终点
  102. this.panel.Children.Add(Vertex.GetHollow(end));
  103. }
  104. this.panel.Width = end.X + 500;
  105. }
  106. double width = 160;
  107. double perHeight = 60;
  108. private Point DrawNode(LogicNode ln1, Point end, double top) {
  109. if (ln1 == null) return end;
  110. //避免移除数据对原始数据造成影响
  111. var ln = new LogicNode { Name = ln1.Name };
  112. ln1.Nodes.ForEach(ln.Nodes.Add);
  113. if (ln.Nodes.Count == 0) return end;
  114. var node = ln.Nodes[0];
  115. for (int i = 0; i < ln.Nodes.Count; i++) {
  116. bool isAddLine = false;
  117. //当前节点为子节点
  118. if (node.Nodes.Count == 0) {
  119. continue;
  120. }
  121. //当前节点的子节点也包含子节点
  122. if (node.Nodes.Any(t => t.Nodes.Count > 0)) {
  123. end = DrawNode(node, end, top);
  124. continue;
  125. }
  126. var m = node.Nodes.Count;
  127. // "地源热泵|供冷冷却水泵|供冷冷冻水泵|地埋管|流量传感器|压力传感器|温度传感器";
  128. var regStr = @"^(CCWH|CCOP|CCCP|CCGHBP|SEFL|SEPS|SETP)-\w+";
  129. var names = node.Nodes.Select(t1 => {
  130. var elment = t1.Elements.FirstOrDefault(t => Regex.IsMatch(t.FamilyName ?? "", regStr));
  131. if (elment != null) return elment.Sno + ":" + elment.Name;
  132. return "";
  133. }).ToList();
  134. if (node.RelationType == ChildrenRelationType.ParallelCon) {
  135. top = perHeight * (m - 1) / 2.0d;
  136. //找出最长子节点
  137. var maxLen = node.Nodes.Max(t1 =>
  138. t1.Elements.Count(t => Regex.IsMatch(t.FamilyName ?? "", regStr))
  139. );
  140. var length = Math.Max(0, width * (maxLen - 1));//楼层为maxLen为0
  141. //设备并联
  142. for (int j = 0; j < m; j++) {
  143. var nodeNames = node.Nodes[j].Elements.Where(t => Regex.IsMatch(t.FamilyName ?? "", regStr))
  144. .Select(t => t.Sno + ":" + t.Name).ToList();
  145. //加入楼层
  146. var floorNames = node.Nodes[j].Elements.Where(t => t.Id == "")
  147. .Select(t => t.Name).ToList();
  148. nodeNames.AddRange(floorNames);
  149. var point = end.AddX(width).AddY(-top + perHeight * j);
  150. // ShowText(point, names[j]);
  151. //连线
  152. this.panel.Children.Add(new SgLine(end.AddX(6), point));
  153. // this.panel.Children.Add(new Vertex(point));//增加传感器串联20171225
  154. var curWidth = nodeNames.Count <= 1 ? 0 : length / (nodeNames.Count - 1);
  155. DrawSeriesCon(point, nodeNames, curWidth);
  156. this.panel.Children.Add(new SgLine(end.AddX(-6 + length + 2 * width), point.AddX(length)));
  157. }
  158. end = end.AddX(length + 2 * width);
  159. isAddLine = true;
  160. }
  161. else if (node.RelationType == ChildrenRelationType.SeriesCon) {
  162. //设备串联
  163. DrawSeriesCon(end.AddX(width), names, width);
  164. end = end.AddX(width * (m + 1));
  165. //补一个连接线
  166. this.panel.Children.Add(new SgLine(end.AddX(6 - width), end));
  167. }
  168. //增加终点
  169. this.panel.Children.Add(Vertex.GetHollow(end));
  170. //移除当前元素,避免查找污染
  171. ln.Nodes.Remove(node);
  172. i--;
  173. node = ln.Nodes.FirstOrDefault(t => IsConnector(t, node));
  174. //if (node != null &&
  175. // node.RelationType == ChildrenRelationType.ParallelCon &&
  176. // isAddLine) {
  177. end = end.AddX(width);
  178. //增加终点连接线
  179. this.panel.Children.Add(new SgLine(end.AddX(6 - width), end.AddX(-6)));
  180. //增加下一组的起点
  181. this.panel.Children.Add(Vertex.GetHollow(end));
  182. //}
  183. if (node == null) break;
  184. }
  185. return end;
  186. }
  187. private void DrawSeriesCon(Point end, List<string> names, double nodeWidth) {
  188. var m = names.Count;
  189. for (int j = 0; j < m; j++) {
  190. var point = end.AddX(nodeWidth * j);
  191. ShowText(point, names[j]);
  192. //连线
  193. if (j < m - 1)//最后一条线不连
  194. {
  195. this.panel.Children.Add(new SgLine(point.AddX(6 + nodeWidth), point));
  196. }
  197. var v = new Vertex(point) {
  198. ShowAction = (eid) => {
  199. if (string.IsNullOrEmpty(eid))//只有楼层Eid为空
  200. {
  201. WinDrawEndPoint winDraw = new WinDrawEndPoint();
  202. winDraw.ShowDialog();
  203. }
  204. }
  205. };
  206. this.panel.Children.Add(v);
  207. // this.panel.Children.Add(new SgLine(end.AddX(-6), point));
  208. }
  209. }
  210. private void ShowText(Point end, double top, string name) {
  211. TextBlock tb = new TextBlock() {
  212. Width = 100,
  213. TextAlignment = TextAlignment.Center,
  214. Text = name
  215. };
  216. Canvas.SetTop(tb, end.Y - top - 20);
  217. Canvas.SetLeft(tb, end.X + width - tb.Width / 2.0d);
  218. this.panel.Children.Add(tb);
  219. }
  220. private void ShowText(Point end, string name) {
  221. TextBlock tb = new TextBlock() {
  222. Width = 100,
  223. Height = 20,
  224. TextAlignment = TextAlignment.Center,
  225. Text = name
  226. };
  227. Canvas.SetTop(tb, end.Y - 15 - tb.Height);
  228. Canvas.SetLeft(tb, end.X - tb.Width / 2.0d);
  229. this.panel.Children.Add(tb);
  230. }
  231. public bool IsConnector(LogicNode node1, LogicNode node2) {
  232. if (node1 == null || node2 == null) return false;
  233. if (node1 == node2) return false;
  234. return node1.RealNodes.Any(n => node2.RealNodes.
  235. Any(n1 => n.ToString() == n1.ToString()));
  236. }
  237. private double scaleValue = 1;
  238. private void Canvas_OnMouseWheel(object sender, MouseWheelEventArgs e) {
  239. //TODO:影响文字的位置
  240. //if (scaleValue < 0.3 && scaleValue < 0.3 && e.Delta < 0) {
  241. // return;
  242. //}
  243. //double val = (double)e.Delta / 2000; //描述鼠标滑轮滚动
  244. //scaleValue += val;
  245. //MoveElement(panel, x, y, scaleValue);
  246. }
  247. private void RootNode_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) {
  248. if (rootNode.SelectedItem is LogicNode ln) {
  249. var data = m_data.Nodes.FirstOrDefault(m => m.Name == ln.Name);
  250. Draw(data);
  251. }
  252. }
  253. private bool isMouseLeftButtonDown = false;
  254. Point previousMousePoint = new Point(0, 0);
  255. private void panel_MouseDown(object sender, MouseButtonEventArgs e) {
  256. if (e.LeftButton == MouseButtonState.Pressed) {
  257. isMouseLeftButtonDown = true;
  258. previousMousePoint = e.GetPosition(panel);
  259. }
  260. this.Cursor = Cursors.Hand;
  261. }
  262. private double x = 0;
  263. private double y = 0;
  264. private void panel_MouseUp(object sender, MouseButtonEventArgs e) {
  265. if (isMouseLeftButtonDown) {
  266. Point position = e.GetPosition(panel);
  267. x += position.X - this.previousMousePoint.X;
  268. y += position.Y - this.previousMousePoint.Y;
  269. }
  270. isMouseLeftButtonDown = false;
  271. this.Cursor = Cursors.Arrow;
  272. }
  273. private void panel_MouseMove(object sender, MouseEventArgs e) {
  274. if (e.LeftButton == MouseButtonState.Pressed) {
  275. Point position = e.GetPosition(panel);
  276. var tempx = position.X - this.previousMousePoint.X;
  277. var tempy = position.Y - this.previousMousePoint.Y;
  278. var x0 = x + tempx;
  279. var y0 = y + tempy;
  280. MoveElement(panel, x0, y0, scaleValue);
  281. }
  282. }
  283. /// <summary>
  284. /// 双击滚轮,缩放匹配
  285. /// </summary>
  286. /// <param name="e"></param>
  287. protected override void OnMouseDown(MouseButtonEventArgs e) {
  288. base.OnMouseDown(e);
  289. if (e.ChangedButton == MouseButton.Middle) {
  290. if (panel.InputHitTest(e.GetPosition(panel)) is Canvas && e.ClickCount == 2) {
  291. scaleValue = 1;
  292. x = 0;
  293. y = 0;
  294. MoveElement(panel, x, y, scaleValue);
  295. }
  296. }
  297. }
  298. /// <summary>
  299. /// 平移Canvas中的元素,
  300. /// 由于TranslateTransform是平移画布,所有采用平移元素的方式
  301. /// </summary>
  302. /// <param name="canvas"></param>
  303. /// <param name="dx"></param>
  304. /// <param name="dy"></param>
  305. private void MoveElement(Canvas canvas, double dx, double dy, double scale) {
  306. foreach (UIElement s in canvas.Children) {
  307. TransformGroup transformGroup = new TransformGroup();
  308. TranslateTransform translateTransform = new TranslateTransform {
  309. X = dx,
  310. Y = dy
  311. };
  312. transformGroup.Children.Add(translateTransform);
  313. ScaleTransform scaleTransform = new ScaleTransform {
  314. ScaleX = scale,
  315. ScaleY = scale
  316. };
  317. transformGroup.Children.Add(scaleTransform);
  318. s.RenderTransform = transformGroup;
  319. }
  320. }
  321. private void win_SizeChanged(object sender, SizeChangedEventArgs e) {
  322. this.panel.Width = e.NewSize.Width - 150;
  323. this.panel.Height = e.NewSize.Height - 20;
  324. }
  325. }
  326. public static class ExtertMethods {
  327. public static Point AddX(this Point point, double x) {
  328. return new Point(point.X + x, point.Y);
  329. }
  330. public static Point AddY(this Point point, double y) {
  331. return new Point(point.X, point.Y + y);
  332. }
  333. public static Point Add(this Point point, Point point1) {
  334. return new Point(point.X + point.X, point.Y + point1.Y);
  335. }
  336. public static Point Mult(this Point point, Point point1) {
  337. return new Point(point.X - point1.X, point.Y - point1.Y);
  338. }
  339. }
  340. public class NameVisibility : IValueConverter {
  341. public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
  342. if (value == null) {
  343. return System.Windows.Visibility.Collapsed;
  344. }
  345. else {
  346. return System.Windows.Visibility.Visible;
  347. }
  348. }
  349. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
  350. throw new NotImplementedException();
  351. }
  352. }
  353. }