//获取所有分支
        private List <string> GetAllBranch(TreeNodes rootTree)
        {
            //获取所有的线
            List <string> mrvBranch = new List <string>();

            InitTreeWithDepth(rootTree);
            SearchAllBranch(rootTree, mrvBranch, 'a', 0);
            SortByLengthWithList(mrvBranch);
            return(mrvBranch);
        }
        /// <summary>
        /// 绘图
        /// </summary>
        /// <param name="rootTree"></param>
        /// <returns></returns>
        private MDocument WriteBrachTree(TreeNodes rootTree)
        {
            //获取所有分支
            List <string> listBranch = GetAllBranch(rootTree);

            //开始遍历子节点
            _ListTextPosition = new List <string>();
            MDocument md = WriteBranchWithMD(listBranch);

            return(md);
        }
        /// <summary>
        /// 找当前节点的最长路线(反向输出路线)
        /// </summary>
        /// <param name="node"></param>
        /// <param name="isRoots">用于判断当前分支是否是最长分支搜索</param>
        /// <returns></returns>
        private string GetMaxLengthRoute(TreeNodes node, bool isRoots, char index, int level)
        {
            node.IsSearch = true;
            if (node.Children.Count == 0)
            {
                return(node.Smiles + ";" + level + index);
            }
            int       dept  = -1;
            TreeNodes temp  = new TreeNodes();
            int       i     = 0;
            int       tag_i = 0;

            foreach (var item in node.Children)
            {
                if (dept < item.MaxDepth)
                {
                    dept  = item.MaxDepth;
                    temp  = item;
                    tag_i = i;
                }
                i++;
            }
            if (isRoots)
            {
                string str = string.Empty;
                int    j   = 0;
                foreach (var item in node.Children)
                {
                    if (item.NodeID != temp.NodeID)
                    {
                        if (string.IsNullOrEmpty(str))
                        {
                            str += item.Smiles + ";" + (level + 1) + Convert.ToChar('a' + j);
                        }
                        else
                        {
                            str += "," + item.Smiles + ";" + (level + 1) + Convert.ToChar('a' + j);
                        }
                    }
                    j++;
                }
                if (DicBranchSmiles == null)
                {
                    DicBranchSmiles = new Dictionary <int, string>();
                }
                DicBranchSmiles.Add(temp.MaxDepth, str);
            }
            char childIndex = Convert.ToChar('a' + tag_i);

            return(GetMaxLengthRoute(temp, isRoots, childIndex, level + 1) + "," + node.Smiles + ";" + level + index);
        }
        /// <summary>
        /// 绘图
        /// </summary>
        /// <param name="rootTree"></param>
        /// <returns></returns>
        private MDocument WriteTree(TreeNodes rootTree)
        {
            MoleCulePostion mp = new MoleCulePostion(rootTree.Smiles);
            MDocument       md = new MDocument(mp.Mol);

            //初始化树的叶子节点数量
            InitTreeLeapNum(rootTree);

            //开始遍历子节点
            _DicListTextPosition = new Dictionary <int, List <string> >();
            _DicListTextPosition.Add(0, new List <string>()); //上
            _DicListTextPosition.Add(1, new List <string>()); //中
            _DicListTextPosition.Add(2, new List <string>()); //下
            SearchChildNode(rootTree, md, mp, mp.Mol, 1);
            return(md);
        }
        /// <summary>
        /// 返回整个路线列表
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public string WriteToMrvWithAllRouteWithStr(string result)
        {
            //取根路线
            List <TreeNodes> treeNodes = JsonConvert.DeserializeObject <List <TreeNodes> >(result);
            TreeNodes        rootTree  = new TreeNodes();

            foreach (var item in treeNodes)
            {
                if (item.PID == 0)
                {
                    rootTree = item;
                }
            }
            //树绘图
            MDocument md = WriteTree(rootTree);

            return(MolExporter.exportToFormat(md, "mrv"));
        }
        /// <summary>
        /// 初始化树的叶子节点数量
        /// </summary>
        /// <param name="rootTree"></param>
        /// <returns></returns>
        private void InitTreeLeapNum(TreeNodes treeNode)
        {
            int num = 0;

            foreach (var item in treeNode.Children)
            {
                if (item.Children.Count == 0)
                {
                    item.ChildLeapNum = 1;
                }
                else
                {
                    InitTreeLeapNum(item);
                }
                num += item.ChildLeapNum;
            }
            treeNode.ChildLeapNum = num;
        }
        /// <summary>
        /// 找到所有不存在重复分子的分支
        /// </summary>
        /// <param name="node"></param>
        /// <param name="mrvBranch"></param>
        private void SearchAllBranch(TreeNodes node, List <string> mrvBranch, char index, int level)
        {
            if (node.IsSearch == false)
            {
                //找当前节点的最长路线
                string route = GetMaxLengthRoute(node, node.PID == 0 ? true : false, index, level);
                if (route.Split(',').Count() > 1)
                {
                    mrvBranch.Add(route);
                }
                node.IsSearch = true;
            }
            int i = 0;

            foreach (var item in node.Children)
            {
                SearchAllBranch(item, mrvBranch, Convert.ToChar('a' + i++), level + 1);
            }
        }
        /// <summary>
        /// 初始化树所有节点的长度
        /// </summary>
        /// <param name="rootTree"></param>
        private void InitTreeWithDepth(TreeNodes node)
        {
            if (node.Children.Count == 0)
            {
                node.MaxDepth = 1;
                return;
            }
            int childDept = -1;

            foreach (var item in node.Children)
            {
                InitTreeWithDepth(item);
                if (item.MaxDepth > childDept)
                {
                    childDept = item.MaxDepth;
                }
            }
            node.MaxDepth = 1 + childDept;
        }
        /// <summary>
        /// 返回文件流的mrv
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public MemoryStream WriteToMrvWithBranch(string result)
        {
            //取根路线
            List <TreeNodes> treeNodes = JsonConvert.DeserializeObject <List <TreeNodes> >(result);
            TreeNodes        rootTree  = new TreeNodes();

            foreach (var item in treeNodes)
            {
                if (item.PID == 0)
                {
                    rootTree = item;
                }
            }
            //树绘图
            MDocument    md     = WriteBrachTree(rootTree);
            MemoryStream stream = new MemoryStream(MolExporter.exportToBinFormat(md, "cdx"));

            return(stream);
        }
 public TreeNodes(TreeNodes fatherNode, Reaction react)
 {
     //NodeID = nodeID;
     Smiles = react.smilesInCode;
     if (fatherNode != null)
     {
         father = fatherNode;
         //PID = father.NodeID;
         level          = father.level + 1;
         searchedSmiles = father.searchedSmiles.ToList();
         father.Children.Add(this);
     }
     reaction = react;
     CAS      = react.cas;
     //MolPrice = react.MolPrice;
     //reaction = new ReturnList();
     //reaction.reactionObject = new List<Reaction>();
     //Reaction re = react;
     ////re.smilesInCode = react;
     //reaction.reactionObject.Add(re);
     searchedSmiles.Add(Smiles);
 }
        /// <summary>
        /// 遍历子节点加入画图中
        /// </summary>
        /// <param name="node">当前节点</param>
        /// <param name="md">画图对象</param>
        /// <param name="previousMp">前一个节点的位置坐标对象</param>
        /// <param name="RootMol">根mol</param>
        /// <param name="level">层级</param>
        private void SearchChildNode(TreeNodes node, MDocument md, MoleCulePostion previousMp, Molecule RootMol, int bracnchIndex)
        {
            double molLeftSpace = 0;
            int    num          = node.Children.Count;

            if (num == 1)
            {
                TreeNodes childNode = node.Children[0];
                //绘制
                MoleCulePostion mp = new MoleCulePostion(childNode.Smiles);
                molLeftSpace = mp.Center_x - mp.Left_x;
                SetMolPosition(mp, previousMp.Right_x + SpanceX + molLeftSpace, previousMp.Center_y);
                RootMol.fuse(mp.Mol);
                //写mol层次号
                string txt = ReactionSteps.ToString() + "a";
                _DicListTextPosition[bracnchIndex].Add(txt + "," + mp.Center_x + "," + (mp.Bottom_y - TxtspaceWithMolInY));

                //划水平线
                MPoint     p1    = new MPoint(previousMp.Right_x + SpanceX * (0.5 - SpaceLineScale / 2), previousMp.Center_y);
                MPoint     p2    = new MPoint(previousMp.Right_x + SpanceX * (0.5 + SpaceLineScale / 2), previousMp.Center_y);
                MRectangle arrow = new MRectangle(p1, p2);
                md.addObject(arrow);
                //写反应步次
                md.addObject(CreateMTextBox((ReactionSteps++).ToString(),
                                            new MPoint(previousMp.Right_x + SpanceX * 0.5, previousMp.Center_y + ReactionIndexSpaceWithLine)));

                //遍历子集
                SearchChildNode(childNode, md, mp, RootMol, bracnchIndex);
            }
            else if (num > 1)
            {
                WriteText(md, bracnchIndex);
                if (num % 2 == 0)
                {
                    //对称式绘出节点位置
                    double        topY     = previousMp.Center_y;
                    double        bottomY  = previousMp.Center_y;
                    List <double> listHigh = new List <double>();
                    List <char>   listChar = new List <char>();
                    for (int i = 0; i < num; i++)
                    {
                        listChar.Add((char)('a' + i));
                    }
                    var list = node.Children;
                    for (int i = 0; i < list.Count; i += 2)
                    {
                        //记录当前反应的步数
                        int    curStep = ReactionSteps++;
                        double tempY1  = list[i].ChildLeapNum * SpanceY;
                        double tempY2  = list[i + 1].ChildLeapNum * SpanceY;

                        topY    += tempY1 > tempY2 ? tempY1 : tempY2;
                        bottomY -= tempY1 > tempY2 ? tempY1 : tempY2;
                        listHigh.Add(topY);
                        listHigh.Add(bottomY);
                        //上半部分
                        MoleCulePostion mp1 = new MoleCulePostion(list[i].Smiles);
                        molLeftSpace = mp1.Center_x - mp1.Left_x;
                        SetMolPosition(mp1, previousMp.Right_x + SpanceX + molLeftSpace, topY);
                        RootMol.fuse(mp1.Mol);
                        //写mol层次号
                        string txt1 = curStep.ToString() + listChar[num - (num / 2 + i / 2) - 1];
                        _DicListTextPosition[0].Add(txt1 + "," + mp1.Center_x + "," + (mp1.Bottom_y - TxtspaceWithMolInY));
                        //找子集
                        SearchChildNode(list[i], md, mp1, RootMol, 0);

                        //下半部分
                        MoleCulePostion mp2 = new MoleCulePostion(list[i + 1].Smiles);
                        molLeftSpace = mp2.Center_x - mp2.Left_x;
                        SetMolPosition(mp2, previousMp.Right_x + SpanceX + molLeftSpace, bottomY);
                        RootMol.fuse(mp2.Mol);
                        //写mol层次号
                        string txt2 = curStep.ToString() + listChar[num / 2 + i / 2];
                        _DicListTextPosition[2].Add(txt2 + "," + mp2.Center_x + "," + (mp2.Bottom_y - TxtspaceWithMolInY));
                        //写反应步次
                        double startWithText = 0.5 - SpaceLineScale / 4;
                        md.addObject(CreateMTextBox((curStep).ToString(),
                                                    new MPoint(previousMp.Right_x + SpanceX * startWithText, previousMp.Center_y + ReactionIndexSpaceWithLine)));
                        WriteBranchLine(previousMp.Right_x, previousMp.Center_y, listHigh, md);

                        //找子集
                        SearchChildNode(list[i + 1], md, mp2, RootMol, 2);
                    }
                }
                else
                {
                    //记录当前反应的步数
                    int           curStep  = ReactionSteps++;
                    double        topY     = previousMp.Center_y;
                    double        bottomY  = previousMp.Center_y;
                    List <double> listHigh = new List <double>();
                    List <char>   listChar = new List <char>();
                    for (int i = 0; i < num; i++)
                    {
                        listChar.Add((char)('a' + i));
                    }
                    var list = node.Children;
                    //先绘画水平节点
                    MoleCulePostion mp = new MoleCulePostion(list[0].Smiles);
                    molLeftSpace = mp.Center_x - mp.Left_x;
                    SetMolPosition(mp, previousMp.Right_x + SpanceX + molLeftSpace, previousMp.Center_y);
                    RootMol.fuse(mp.Mol);
                    //写mol层次号
                    string txt = curStep.ToString() + listChar[num / 2];
                    _DicListTextPosition[1].Add(txt + "," + mp.Center_x + "," + (mp.Bottom_y - TxtspaceWithMolInY));
                    //找子集
                    SearchChildNode(list[0], md, mp, RootMol, 1);
                    //分隔两侧间距
                    double high_mp = list[0].ChildLeapNum * SpanceY;
                    topY    += high_mp;
                    bottomY -= high_mp;
                    listHigh.Add(previousMp.Center_y);
                    //两端节点
                    for (int i = 1; i < list.Count; i += 2)
                    {
                        double tempY1 = list[i].ChildLeapNum * SpanceY;
                        double tempY2 = list[i + 1].ChildLeapNum * SpanceY;

                        topY    += tempY1 > tempY2 ? tempY1 : tempY2;
                        bottomY -= tempY1 > tempY2 ? tempY1 : tempY2;
                        listHigh.Add(topY);
                        listHigh.Add(bottomY);
                        //上半部分
                        MoleCulePostion mp1 = new MoleCulePostion(list[i].Smiles);
                        molLeftSpace = mp1.Center_x - mp1.Left_x;
                        SetMolPosition(mp1, previousMp.Right_x + SpanceX + molLeftSpace, topY);
                        RootMol.fuse(mp1.Mol);
                        //写mol层次号
                        string txt1 = curStep.ToString() + listChar[num / 2 - 1 - i / 2];
                        _DicListTextPosition[0].Add(txt1 + "," + mp1.Center_x + "," + (mp1.Bottom_y - TxtspaceWithMolInY));
                        //找子集
                        SearchChildNode(list[i], md, mp1, RootMol, 0);

                        //下半部分
                        MoleCulePostion mp2 = new MoleCulePostion(list[i + 1].Smiles);
                        molLeftSpace = mp2.Center_x - mp2.Left_x;
                        SetMolPosition(mp2, previousMp.Right_x + SpanceX + molLeftSpace, bottomY);
                        RootMol.fuse(mp2.Mol);
                        //写mol层次号
                        string txt2 = curStep.ToString() + listChar[num / 2 + 1 + i / 2];
                        _DicListTextPosition[2].Add(txt2 + "," + mp2.Center_x + "," + (mp2.Bottom_y - TxtspaceWithMolInY));

                        //写反应步次
                        double startWithText = 0.5 - SpaceLineScale / 4;
                        md.addObject(CreateMTextBox((curStep).ToString(), new MPoint(previousMp.Right_x + SpanceX * startWithText, previousMp.Center_y + ReactionIndexSpaceWithLine)));
                        WriteBranchLine(previousMp.Right_x, previousMp.Center_y, listHigh, md);
                        //找子集
                        SearchChildNode(list[i + 1], md, mp2, RootMol, 2);
                    }
                }
            }
            else
            {
                WriteText(md, bracnchIndex);
            }
        }
        // build treenodes from root
        private TreeNodes createTreeNodes()
        {
            // root
            Reaction reac = new Reaction();

            reac.canMake      = targetReactif.canMake;
            reac.smilesInCode = targetReactif.smilesInCode;
            reac.knownMol     = targetReactif.knownMol;
            TreeNodes treeRoot = new TreeNodes();

            treeRoot.reaction    = reac;
            treeRoot.Smiles      = reac.smilesInCode;
            treeRoot.Feasibility = ((reaction.HasRegioError != 0 || reaction.Retro.MayHaveError != 0) ? 1 : 0)
                                   + reaction.Retro.IncompatbleIDs.Count + reaction.Retro.UncertantIncompatbleIDs.Count;
            treeRoot.ComboRetroReactionID  = reaction.Retro.ComboRetroReactionID;
            treeRoot.ComboRetroReactionIDs = reaction.Retro.ComboRetroReactionIDs;
            treeRoot.prodcdid         = reaction.similCdid;
            treeRoot.RetroReactionID  = reaction.Retro.RetroReactionID;
            treeRoot.RetroReactionIDs = reaction.Retro.RetroReactionIDs;
            treeRoot.fiabilityScore   = reaction.Retro.fiabilityScore;
            treeRoot.needProtection   = reaction.Retro.NeedProtection;
            treeRoot.reactionId       = reaction.reactionID;
            //if (reaction.Retro.groupDetail != null && reaction.Retro.groupDetail.Count > 0)
            //{
            //    var mingroup = reaction.Retro.groupDetail.FirstOrDefault();
            //    treeRoot.testString = (((reaction.HasRegioError + reaction.Retro.MayHaveError) > 0 ? " regio" : "") + reaction.Retro.Frequency.ToString("0.0000") + " " + GroupInfo.groupNameDict[mingroup.Key] + " " + mingroup.Value.count + " " + mingroup.Value.Score.ToString("0.00"));
            //}
            //else
            //{
            //    treeRoot.testString = (((reaction.HasRegioError + reaction.Retro.MayHaveError) > 0 ? " regio" : "") + reaction.Retro.Frequency.ToString("0.0000"));
            //}
            //treeRoot.testString = reaction.similRank.ToString("0.00") + " " + reaction.Retro.fiabilityScore;//reaction.Retro.Count + " " + groupRank; //reaction.Retro.TotalCount + "-" + reaction.Retro.RetroTypeCount;//
            treeRoot.testString     = ((reaction.Retro.IncompatbleIDs.Count + reaction.Retro.UncertantIncompatbleIDs.Count) > 0 ? "compat" : "") + ((reaction.HasRegioError + reaction.Retro.MayHaveError) > 0 ? " regio" : "") + ChoiseRank + "_" + RankIndexSimil + "|" + RankIndexScore;
            treeRoot.ChoiseRank     = ChoiseRank;
            treeRoot.RankIndexSimil = RankIndexSimil;
            treeRoot.RankIndexScore = RankIndexScore;

            if (reaction.reactionObject != null)
            {
                foreach (var react in reaction.reactionObject)
                {
                    Node current;
                    if (react.currentChildNode != null && react.currentChildNode.useCurrent)
                    {
                        current = react.currentChildNode;
                        react.currentChildNode.useCurrent = false;
                    }
                    else
                    {
                        current = react.BestChildNode;
                    }
                    if (current == null)
                    {
                        TreeNodes treeRoot1 = new TreeNodes();
                        treeRoot1.reaction              = new Reaction();
                        treeRoot1.reaction.canMake      = react.canMake;
                        treeRoot1.reaction.MoleculeID   = react.MoleculeID;
                        treeRoot1.reaction.smilesInCode = react.smilesInCode;
                        treeRoot1.Smiles = react.smilesInCode;
                        treeRoot1.CAS    = react.cas;
                        if (treeRoot1.reaction.canMake == 1)
                        {
                            treeRoot1.reaction.MolPrice = react.MolPrice;
                        }
                        treeRoot1.reaction.HasSupplier = react.HasSupplier;
                        treeRoot1.reaction.knownMol    = react.knownMol;
                        treeRoot.Children.Add(treeRoot1);
                        continue;
                    }
                    Node child = current;

                    treeRoot.Children.Add(child.createTreeNodes());
                }
            }
            return(treeRoot);
        }