zoukankan      html  css  js  c++  java
  • 遍历一个树的所有子节点,画出该树,深度不定,广度不定,适用于任何树,深度优先算法

      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     }
  • 相关阅读:
    js多图上传展示和删除
    简单的下拉加载和上拉加载
    js实现放大镜效果
    js表格拖拽
    js表格上下移动添加删除
    js写的滑动解锁
    关于serialize() FormData serializeArray()表单序列化
    js日历
    js树状菜单
    Restful API官方文档
  • 原文地址:https://www.cnblogs.com/albertay/p/6762625.html
Copyright © 2011-2022 走看看