C# 在同一级别绘制节点

C# 在同一级别绘制节点,c#,C#,我试图创建一个包含一些节点和边缘的json数据 {"nodes":[ {"id":0,"title":"a","x":1200,"y":50}, {"id":1,"title":"b","x":800,"y":200}, {"id":2,"title":"c","x":1200,"y":200}, {"id":3,"title":"d","x":1200,"y":400},

我试图创建一个包含一些节点和边缘的json数据

 {"nodes":[
            {"id":0,"title":"a","x":1200,"y":50},
            {"id":1,"title":"b","x":800,"y":200},
            {"id":2,"title":"c","x":1200,"y":200},
            {"id":3,"title":"d","x":1200,"y":400},
            {"id":4,"title":"e","x":800,"y":400},
            {"id":5,"title":"f","x":1000,"y":500}],
"edges":[
            {"source":0,"target":2},
            {"source":1,"target":3},
            {"source":2,"target":3},
            {"source":1,"target":4},
            {"source":2,"target":4},
            {"source":3,"target":5},
            {"source":4,"target":5}]
}
我在这里硬编码了“x”和“y”值。我想生成那些“x”和“y”值,以便相同深度的节点保持在相同的级别。在硬编码值之前,我使用以下方法生成这些值:

strJosn.Append("{\"id\":" + i + ",\"title\":\"" + nodeNames[i] + "\",\"x\":" + GetRandomNumber(arlRandom) + ",\"y\":" + GetRandomNumber(arlRandom));
我的csv数据如下所示:

第一列上方表示子列,第二列之后表示第一列中子列的父节点。 对应的树如下所示

如何生成这些值,以使节点在图中所示的相同级别上对齐

编辑:
我已将csv数据存储在dataTable中。

我已创建了一个类
节点
,它并不完美,但运行良好:

internal class Node
{
    public Node Parent { get; set; }
    private Node m_child;
    public Node Child
    {
        get { return m_child; }
        set
        {
            m_child = value;
            value.Parent = this;
        }
    }
    public int Id { get; set; }
    public string Title { get; set; }
}
internal class Program
{
    static void Main(string[] args)
    {
        Dictionary<int, Node> nodes = new Dictionary<int, Node>()
        {
            {0, new Node() {Id = 0, Title = "a"}},
            {1, new Node() {Id = 1, Title = "b"}},
            {2, new Node() {Id = 2, Title = "c"}},
            {3, new Node() {Id = 3, Title = "d"}},
            {4, new Node() {Id = 4, Title = "e"}},
            {5, new Node() {Id = 5, Title = "f"}}
        };

        nodes[0].Child = nodes[2];
        nodes[1].Child = nodes[3];
        nodes[2].Child = nodes[3];
        nodes[1].Child = nodes[4];
        nodes[2].Child = nodes[4];
        nodes[3].Child = nodes[5];
        nodes[4].Child = nodes[5];


        Dictionary<int, List<Node>> nbParentNodesDictionary = new Dictionary<int, List<Node>>();
        foreach (KeyValuePair<int, Node> valuePair in nodes)
        {
            Node parent = valuePair.Value.Parent;
            int nbOfParent = 0;
            while (parent != null)
            {
                nbOfParent++;
                parent = parent.Parent;
            }
            if (!nbParentNodesDictionary.ContainsKey(nbOfParent))
            {
                nbParentNodesDictionary[nbOfParent] = new List<Node>();
            }
            nbParentNodesDictionary[nbOfParent].Add(valuePair.Value);
        }

        const int yOffSet = 100;

        foreach (KeyValuePair<int, List<Node>> keyValuePair in nbParentNodesDictionary)
        {
            const int xMax = 500;
            int xOffset = xMax/(keyValuePair.Value.Count+1);
            int x = 0;
            foreach (Node node in keyValuePair.Value)
            {
                x += xOffset ;
                Console.Out.WriteLine("id:" + node.Id + " title:" + node.Title + " x:" + x + " y:" + yOffSet * keyValuePair.Key);
            }
        }
    }
}
内部类节点
{
公共节点父节点{get;set;}
私有节点m_子节点;
公共节点子节点
{
获取{return m_child;}
设置
{
m_child=值;
value.Parent=this;
}
}
公共int Id{get;set;}
公共字符串标题{get;set;}
}
内部课程计划
{
静态void Main(字符串[]参数)
{
字典节点=新字典()
{
{0,新节点(){Id=0,Title=“a”},
{1,新节点(){Id=1,Title=“b”},
{2,新节点(){Id=2,Title=“c”},
{3,新节点(){Id=3,Title=“d”},
{4,新节点(){Id=4,Title=“e”},
{5,新节点(){Id=5,Title=“f”}
};
节点[0]。子节点=节点[2];
节点[1]。子节点=节点[3];
节点[2]。子节点=节点[3];
节点[1]。子节点=节点[4];
节点[2]。子节点=节点[4];
节点[3]。子节点=节点[5];
节点[4]。子节点=节点[5];
字典nbParentNodesDictionary=新字典();
foreach(节点中的KeyValuePair-valuePair)
{
节点父节点=valuePair.Value.parent;
int-nbOfParent=0;
while(父级!=null)
{
nbOfParent++;
父=父。父;
}
如果(!nbParentNodesDictionary.ContainsKey(nbOfParent))
{
nbParentNodesDictionary[nbOfParent]=新列表();
}
nbParentNodesDictionary[nbOfParent].Add(valuePair.Value);
}
const int yOffSet=100;
foreach(nbParentNodesDictionary中的KeyValuePair KeyValuePair)
{
常数int xMax=500;
int xOffset=xMax/(keyValuePair.Value.Count+1);
int x=0;
foreach(keyValuePair.Value中的节点)
{
x+=xOffset;
Console.Out.WriteLine(“id:+node.id+”title:+node.title+”x:+x+”y:+yOffSet*keyValuePair.Key”);
}
}
}
}
哪些产出:

id:0标题:a x:166 y:0

id:1标题:b x:332 y:0

id:2标题:c x:250 y:100

id:3标题:d x:166 y:200

id:4标题:EX:332 y:200

id:5标题:f x:250 y:300


我认为问题陈述需要一些澄清;由于无向循环显然在图中是允许的,“水平”的确切概念是什么?是否要求边缘指向较低的标高?如果是这样,可能会有帮助。@Codor,级别只是Y值(纵坐标)。是的,边应该指向较低的级别。您从哪里获得这些数据的?一个
节点
类或什么的?,从这里开始。你可以下载它。我想通过上传创建的数据来创建我自己的图表。@Thomas,你能找到这些数据吗?非常感谢你的回答。我们不能从csv文件中获取输入并执行它吗?@Artiga我们可以,但也许你可以试试;)当然可以谢谢托马斯的帮助。:)我试着使用csv,但效果很好。您提供的逻辑有时会使孩子的位置高于或等于家长的级别。我做了很多尝试,但我还远远没有做到。你能帮帮我吗?