1 public class DrawTreePicture
2 {
3 public static RetroTransformation rt;
4
5 static DrawTreePicture()
6 {
7 rt = new RetroTransformation();
8 }
9
10 private static int height = SettingHelper.GetAppSetingValue("height").TryType<int>(120);
11 private static int span = 60; //SettingHelper.GetAppSetingValue("span").TryType<int>(60);
12 private static int width = SettingHelper.GetAppSetingValue("width").TryType<int>(120);
13 private static int fontsize = SettingHelper.GetAppSetingValue("fontsize").TryType<int>(8);
14
15 public static Stream GetTreePicture(List<TreeNodes> list)
16 {
17 MemoryStream stream = new MemoryStream();
18 if (list.Count <= 0)
19 {
20 return stream;
21 }
22 var p = list.GroupBy(it => it.PID);
23 if (p.Count() <= 0)
24 {
25 return stream;
26 }
27 List<TreeNodes> gen = new List<TreeNodes>();
28 //计算有多少个叶子节点
29 int endNode = 0;
30 for (int i = 0; i < list.Count; i++)
31 {
32 bool isEndNode = true;
33 for (int j = 0; j < list.Count; j++)
34 {
35 if (list[i].NodeID == list[j].PID)
36 {
37 isEndNode = false;
38 break;
39 }
40 }
41 if (isEndNode)
42 {
43 endNode++;
44 gen.Add(list[i]);//放到根集合去
45 }
46 }
47 if (endNode <= 0)
48 {
49 return stream;
50 }
51 var parent_0 = list.Where(it => it.PID == 0);
52 if (parent_0.Count() != 1)//只有一个根节点的时候是符合要求的
53 {
54 return stream;
55 }
56 int layerCount = 0;
57 GetCountLayer(list, parent_0.ToList(), ref layerCount);//得到树的深度
58 int big_Y = (height + span + span) * endNode;//画布高度
59 int big_X = (width + span) * layerCount + span;//画布宽度
60
61 Bitmap bmp = new Bitmap(big_X, big_Y);
62 Graphics g = Graphics.FromImage(bmp);
63 g.Clear(Color.FromArgb(50, Color.White));
64 var def = parent_0.FirstOrDefault(it => it.PID == 0);
65 int k = 0;
66 GetRangeOfTop(def.NodeID, list, ref k); //获取起点的y轴坐标
67 int start_y = k / 2 + span;
68 DrowPicture(span, start_y, def.Smiles, def.CAS, def.HasPrice, def.Yield, def.NodeID, ref g);
69 DrowAllPricture(def.NodeID, span, start_y, list, ref g);//开始遍历画图
70 bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
71 bmp.Dispose();
72 return stream;
73 }
74
75 /// <summary>
76 /// 遍历画图
77 /// </summary>
78 public static void DrowAllPricture(int nodeID, int x, int y, List<TreeNodes> list, ref Graphics g)
79 {
80 if (nodeID == 4)
81 {
82
83 }
84 List<TreeNodes> child = list.Where(it => it.PID == nodeID).OrderBy(it => it.NodeID).ToList();
85 if (child.Count == 1)
86 {
87 int x_child = x + width + span;
88 int y_child = y;
89 DrowPicture(x_child, y_child, child[0].Smiles, child[0].CAS, child[0].HasPrice, child[0].Yield, child[0].NodeID, ref g);
90 DrowLine(x_child - span + 10, y_child + height / 2, x_child - span / 2, y_child + height / 2, ref g);
91 DrowAllPricture(child[0].NodeID, x_child, y_child, list, ref g);
92 }
93 if (child.Count > 1)
94 {
95 int k = 0;
96 //int h = 0;
97 GetLongOfChild(nodeID, list, false, ref k);//计算竖线的长度
98 int new_x = x + width + span;
99 int top_y = y - k / 2;//上顶点的纵轴坐标
100 int buotom_y = y + k / 2;//下顶点的纵轴坐标
101 DrowLine(new_x - 20, top_y + height / 2, new_x - 20, buotom_y + height / 2, ref g);//画线
102 DrowLine(x + width + 10, y + height / 2, x + width + 20, y + height / 2, ref g);
103 int fenDuan = k / (child.Count - 1);
104 for (int i = 0; i < child.Count; i++)//遍历所有的孩子,画出图片
105 {
106 if (nodeID == 1)
107 {
108 }
109
110 if (i == 0)//如果是第一个子节点
111 {
112 DrowPicture(new_x, top_y, child[i].Smiles, child[i].CAS, child[i].HasPrice, child[i].Yield, child[i].NodeID, ref g);
113 DrowLine(new_x - 20, top_y + height / 2, new_x - 10, top_y + height / 2, ref g);
114 DrowAllPricture(child[i].NodeID, new_x, top_y, list, ref g);
115 continue;
116 }
117
118 if (nodeID == 4)
119 {
120
121 }
122 int beforhowLong = 0;
123 for (int j = 0; j <= i; j++)
124 {
125 if (j == 0 || j == i)
126 {
127 int m = 0;
128 GetRangOfLastOrNext(child[i - j].NodeID, list, true, ref m);//最后一个节点
129 beforhowLong += m ;
130 }
131 else
132 {
133 int m = 0;
134 GetRangOfLastOrNext(child[i - j].NodeID, list, false, ref m);//计算上一个节点的垂线长度
135 beforhowLong += m;
136 }
137 }
138 int jisuan_y = top_y + beforhowLong + (span + height) * i;
139 DrowPicture(new_x, jisuan_y, child[i].Smiles, child[i].CAS, child[i].HasPrice, child[i].Yield, child[i].NodeID, ref g);
140 DrowLine(new_x - 20, jisuan_y + height / 2, new_x - 10, jisuan_y + height / 2, ref g);
141 DrowAllPricture(child[i].NodeID, new_x, jisuan_y, list, ref g);
142
143 }
144 }
145 }
146
147 //画图
148 public static void DrowPicture(int x, int y, string smiles, string cas, int hasPrice, string yied, int nodeID, ref Graphics g)
149 {
150
151 try
152 {
153 Stream picture = rt.GetPicture(smiles, "smiles", width.ToString(), height.ToString(), "png", false);
154 System.Drawing.Image img = System.Drawing.Image.FromStream(picture);
155 g.DrawImage(img, x, y, width, height);//画结构式图
156 }
157 catch (Exception ex)
158 {
159 CommonTool.Logger.GetLogger(ex.Source).Error(ex.ToString());
160 }
161 WriteStep(x, y, nodeID, ref g);
162 float fontSize = 8F;
163 Font font = new Font("雅黑", fontSize, FontStyle.Bold);
164 SolidBrush drawBrush = new SolidBrush(Color.LightSlateGray);
165 if (!string.IsNullOrEmpty(cas))
166 {
167 PointF drawPoint = new PointF(x + 10, y + height + 5);
168 g.DrawString("CAS:" + cas, font, drawBrush, drawPoint);
169 }
170
171 if (!string.IsNullOrEmpty(yied))
172 {
173 PointF yied_point = new PointF(x + 10, y + height + 20);
174 g.DrawString(yied, font, drawBrush, yied_point);
175 }
176 if (hasPrice == 1)
177 {
178 PointF point = new PointF();
179 if (!string.IsNullOrEmpty(yied))
180 {
181 point = new PointF(x + 10, y + height + 35);
182 }
183 else
184 {
185 point = new PointF(x + 10, y + height + 20);
186 }
187 SolidBrush brush = new SolidBrush(Color.FromArgb(0, 58, 154));
188 g.DrawString("有报价", font, brush, point);
189 }
190 }
191
192 //画线
193 public static void DrowLine(int x1, int y1, int x2, int y2, ref Graphics g)
194 {
195 Pen myPen = new Pen(Color.LightSlateGray, 2);
196 g.DrawLine(myPen, x1, y1, x2, y2);//画直线,斜线(x1,y1,x2,y2,起点横纵坐标,终点横纵坐标)
197 }
198 //标记反应步骤
199 public static void WriteStep(int x1, int y1, int setpsID, ref Graphics g)
200 {
201 Font font = new Font("雅黑", 8, FontStyle.Bold);
202 SolidBrush drawBrush = new SolidBrush(Color.LightSlateGray);
203 PointF step_point = new PointF(x1 + 4, y1 - 2);
204 g.DrawString($"[{setpsID}]", font, drawBrush, step_point);
205 }
206 //计算长度
207 public static void GetLongOfChild(int nodeID, List<TreeNodes> list, bool isFristOrLast, ref int lins)
208 {
209 List<TreeNodes> child = list.Where(it => it.PID == nodeID).OrderBy(it => it.NodeID).ToList();//获取该父节点的所有孩子;
210 if (child.Count > 1)
211 {
212 if (isFristOrLast)
213 {
214 lins += (height + span) * (child.Count() - 1) / 2;
215 }
216 else
217 {
218 lins += (height + span) * (child.Count() - 1);
219 }
220 }
221 for (int i = 0; i < child.Count; i++)
222 {
223 if (i == 0 || i == child.Count - 1)
224 {
225 GetLongOfChild(child[i].NodeID, list, true, ref lins);
226 }
227 else
228 {
229 GetLongOfChild_All(child[i].NodeID, list, ref lins);
230 }
231 }
232 }
233
234 public static void GetLongOfChild_All(int nodeID, List<TreeNodes> list, ref int lins)
235 {
236 List<TreeNodes> child = list.Where(it => it.PID == nodeID).OrderBy(it => it.NodeID).ToList();//获取该父节点的所有孩子;
237 if (child.Count > 1)
238 {
239 lins += (height + span) * (child.Count() - 1);
240 }
241 for (int i = 0; i < child.Count; i++)
242 {
243 GetLongOfChild_All(child[i].NodeID, list, ref lins);
244 }
245 }
246
247 //获取根节点距离画幕顶端的距离
248 public static void GetRangeOfTop(int nodeID, List<TreeNodes> list, ref int topRang)
249 {
250 List<TreeNodes> child = list.Where(it => it.PID == nodeID).OrderBy(it => it.NodeID).ToList();//获取该父节点的所有孩子;
251 if (child.Count > 1)
252 {
253 GetLongOfChild(nodeID, list, false, ref topRang);
254 GetRangeOfTop(child[0].NodeID, list, ref topRang);
255 }
256 if (child.Count == 1)
257 {
258 GetRangeOfTop(child[0].NodeID, list, ref topRang);
259 }
260 }
261
262 public static void GetRangOfLastOrNext(int nodeID, List<TreeNodes> list, bool isTop, ref int topRang)
263 {
264 List<TreeNodes> child = list.Where(it => it.PID == nodeID).OrderBy(it => it.NodeID).ToList();//获取该父节点的所有孩子;
265 if (child.Count > 1)
266 {
267 GetLongOfChild(nodeID, list, isTop, ref topRang);
268 if (isTop)
269 {
270 GetRangOfLastOrNext(child[0].NodeID, list, true, ref topRang);
271 }
272 else
273 {
274 GetRangOfLastOrNext(child[child.Count - 1].NodeID, list, true, ref topRang);
275 }
276 }
277 if (child.Count == 1)
278 {
279 GetRangOfLastOrNext(child[0].NodeID, list, true, ref topRang);
280 }
281 }
282
283 //计算树的最大深度
284 public static void GetCountLayer(List<TreeNodes> list, List<TreeNodes> child, ref int count)
285 {
286 if (child.Count > 0)
287 {
288 count++;
289 List<TreeNodes> a = new List<TreeNodes>();
290 foreach (TreeNodes item in child)
291 {
292 List<TreeNodes> b = list.Where(it => it.PID == item.NodeID).ToList();
293 if (b.Count > 0)
294 {
295 a.AddRange(b);
296 }
297 }
298 GetCountLayer(list, a, ref count);
299 }
300 }
301 }