تخطيط شجرة العائلة مع DOT/GraphViz
-
20-09-2019 - |
سؤال
أحاول رسم شجرة عائلة مع Dot و Graphviz.
هذا ما لدي حاليا:
# just graph set-up
digraph simpsons {
ratio = "auto"
mincross = 2.0
# draw some nodes
"Abraham" [shape=box, regular=1, color="blue"] ;
"Mona" [shape=box, regular=1, color="pink"] ;
"Clancy" [shape=box, regular=1, color="blue"] ;
"Jackeline" [shape=box, regular=1, color="pink"] ;
"Herb" [shape=box, regular=1, color="blue"] ;
"Homer" [shape=box, regular=1, color="blue"] ;
"Marge" [shape=box, regular=1, color="pink"] ;
"Patty" [shape=box, regular=1, color="pink"] ;
"Selma" [shape=box, regular=1, color="pink"] ;
"Bart" [shape=box, regular=1, color="blue"] ;
"Lisa" [shape=box, regular=1, color="pink"] ;
"Maggie" [shape=box, regular=1, color="pink"] ;
"Ling" [shape=box, regular=1, color="blue"] ;
# creating tiny nodes w/ no label, no color
"ParentsHomer" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsMarge" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
"ParentsBart" [shape=diamond,style=filled,label="",height=.1,width=.1] ;
# draw the edges
"Abraham" -> "ParentsHomer" [dir=none, weight=1] ;
"Mona" -> "ParentsHomer" [dir=none, weight=1] ;
"ParentsHomer" -> "Homer" [dir=none, weight=2] ;
"ParentsHomer" -> "Herb" [dir=none, weight=2] ;
"Clancy" -> "ParentsMarge" [dir=none, weight=1] ;
"Jackeline" -> "ParentsMarge" [dir=none, weight=1] ;
"ParentsMarge" -> "Marge" [dir=none, weight=2] ;
"ParentsMarge" -> "Patty" [dir=none, weight=2] ;
"ParentsMarge" -> "Selma" [dir=none, weight=2] ;
"Homer" -> "ParentsBart" [dir=none, weight=1] ;
"Marge" -> "ParentsBart" [dir=none, weight=1] ;
"ParentsBart" -> "Bart" [dir=none, weight=2] ;
"ParentsBart" -> "Lisa" [dir=none, weight=2] ;
"ParentsBart" -> "Maggie" [dir=none, weight=2] ;
"Selma" -> "Ling" [dir=none, weight=2] ;
}
إذا قمت بتشغيل هذا من خلال DOT (dot simpsons.dot -Tsvg > simpsons.svg
) ، أحصل على التصميم التالي:
ومع ذلك ، أود أن تكون الحواف أكثر "شجرة عائلة"-على غرار: تقع بين شخصين متزوجين مع الخط الرأسي من T المتفرعة مرة أخرى في مقاربة T مقلوبة مع التقسيمات الفرعية الصغيرة لكل من الأطفال ، مثل هذا النموذج ، الذي تم في Kolourpaint:
ما هو بناء جملة DOT الذي يجب أن أستخدمه لتحقيق ذلك؟
المحلول
هنا حل آخر:
digraph simpsons {
subgraph Generation0 {
rank = same
Abraham [shape = box, color = blue]
Mona [shape = box, color = pink]
AbrahamAndMona [shape = point]
Abraham -> AbrahamAndMona [dir = none]
AbrahamAndMona -> Mona [dir = none]
Clancy [shape = box, color = blue]
Jackeline [shape = box, color = pink]
ClancyAndJackeline [shape = point]
Clancy -> ClancyAndJackeline [dir = none]
ClancyAndJackeline -> Jackeline [dir = none]
}
subgraph Generation0Sons {
rank = same
AbrahamAndMonaSons [shape = point]
HerbSon [shape = point]
HomerSon [shape = point]
HerbSon -> AbrahamAndMonaSons [dir = none]
HomerSon -> AbrahamAndMonaSons [dir = none]
MargeSon [shape = point]
PattySon [shape = point]
SelmaSon [shape = point]
MargeSon -> PattySon [dir = none]
PattySon -> SelmaSon [dir = none]
}
AbrahamAndMona -> AbrahamAndMonaSons [dir = none]
ClancyAndJackeline -> PattySon [dir = none]
subgraph Generation1 {
rank = same
Herb [shape = box, color = blue]
Homer [shape = box, color = blue]
Marge [shape = box, color = pink]
Patty [shape = box, color = pink]
Selma [shape = box, color = pink]
HomerAndMarge [shape = point]
Homer -> HomerAndMarge [dir = none]
Marge -> HomerAndMarge [dir = none]
}
HerbSon -> Herb [dir = none]
HomerSon -> Homer [dir = none]
MargeSon -> Marge [dir = none]
PattySon -> Patty [dir = none]
SelmaSon -> Selma [dir = none]
subgraph Generation1Sons {
rank = same
BartSon [shape = point]
LisaSon [shape = point]
MaggieSon [shape = point]
BartSon -> LisaSon [dir = none]
LisaSon -> MaggieSon [dir = none]
}
HomerAndMarge -> LisaSon [dir = none]
subgraph Generation2 {
rank = same
Bart [shape = box, color = blue]
Lisa [shape = box, color = pink]
Maggie [shape = box, color = pink]
Ling [shape = box, color = blue]
}
Selma -> Ling [dir = none]
BartSon -> Bart [dir = none]
LisaSon -> Lisa [dir = none]
MaggieSon -> Maggie [dir = none]
}
والنتيجة:
نصائح أخرى
تقوم Gramps (www.gramps-project.org) بإنشاء ملفات نقطة لأشجار الأسرة ، مع أو بدون عقد زواج. هناك أيضًا طريقة لرؤية هذا في واجهة Gramps نفسها. http://gramps-project.org/wiki/index.php؟title=graph_viewلذلك أود أن أقول ، انظر إلى ناتج شجرة عائلتك على النحو الذي تم إنشاؤه بواسطة Gramps
لا أعتقد أنه يمكنك تناول شجرة عائلة تعسفية وتولي تلقائيًا ملفًا نقاطًا حيث يبدو دائمًا جيدًا في GraphViz.
لكني أعتقد أنك يستطيع اجعلها تبدو جيدة دائمًا إذا كنت:
- استخدم الترتيب = نفس الإجابات الأخرى المذكورة للحصول على اتصالات "T" المطلوبة بواسطة OP
- استخدم خدعة الطلب التي قام بها براين بلانك لمنع الخطوط الغريبة
- لا تفترض عدم الزيجات الثانية والنصف
- ارسم مجموعة فرعية فقط من الشجرة التي تطيع القواعد التالية:
- فليكن الشخص "المركزي"
- إذا كان S له أشقاء ، فتأكد من حق كل منهم.
- إذا كان لدى S زوجة وكان للزوج أشقاء ، فتأكد من أن الزوج على يسار جميع أشقائه.
- لا تظهر أبناء أخيه أو بنات أو عمات أو أعمام زوج S أو S S
- لا تظهر أزواج الأشقاء
- لا تظهر أزواج أشقاء الزوج
- أظهر أطفال S ، ولكن ليس أزواجهم أو أطفالهم
- إظهار والديه وأولياء أمور الزوج
سيؤدي هذا إلى إظهار ما لا يزيد عن 3 أجيال في وقت واحد ، مع S في الجيل الأوسط.
في الصورة أدناه s = هوميروس (تم تعديله قليلاً من نسخة براين بلانغ):
digraph G {
edge [dir=none];
node [shape=box];
graph [splines=ortho];
"Herb" [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
"Homer" [shape=box, regular=0, color="blue", style="bold, filled" fillcolor="lightblue"] ;
"Marge" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Clancy" [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
"Jackeline" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Abraham" [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
"Mona" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Patty" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Selma" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Bart" [shape=box, regular=0, color="blue", style="filled" fillcolor="lightblue"] ;
"Lisa" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
"Maggie" [shape=oval, regular=0, color="red", style="filled" fillcolor="pink"] ;
a1 [shape=diamond,label="",height=0.25,width=0.25];
b1 [shape=circle,label="",height=0.01,width=0.01];
b2 [shape=circle,label="",height=0.01,width=0.01];
b3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Abraham -> a1 -> Mona};
{rank=same; b1 -> b2 -> b3};
{rank=same; Herb; Homer};
a1 -> b2
b1 -> Herb
b3 -> Homer
p1 [shape=diamond,label="",height=0.25,width=0.25];
q1 [shape=circle,label="",height=0.01,width=0.01];
q2 [shape=circle,label="",height=0.01,width=0.01];
q3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Homer -> p1 -> Marge};
{rank=same; q1 -> q2 -> q3};
{rank=same; Bart; Lisa; Maggie};
p1 -> q2;
q1 -> Bart;
q2 -> Lisa;
q3 -> Maggie;
x1 [shape=diamond,label="",height=0.25,width=0.25];
y1 [shape=circle,label="",height=0.01,width=0.01];
y2 [shape=circle,label="",height=0.01,width=0.01];
y3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Clancy -> x1 -> Jackeline};
{rank=same; y1 -> y2 -> y3};
{rank=same; Patty; Selma; Marge};
x1 -> y2;
y1 -> Marge;
y2 -> Patty;
y3 -> Selma;
}
هذا يعطي الشجرة التالية بواسطة GraphViz (مع التعليقات التوضيحية أضفت مع Power Point):
على الرغم من أنه لا يمكنك التحكم في وضع العقدة ، فقد وجدت أنه يمكنك المساعدة في وضع العقدة عن طريق طلب العقد بترتيب مختلف. قمت بإعادة ترتيب بعض العقد كما هو موضح أدناه وحصلت على رسم بياني لم ينتج عنه أي تقاطعات.
الرمز التالي:
digraph G {
edge [dir=none];
node [shape=box];
"Herb" [shape=box, regular=1, color="blue"] ;
"Homer" [shape=box, regular=1, color="blue"] ;
"Marge" [shape=box, regular=1, color="pink"] ;
"Clancy" [shape=box, regular=1, color="blue"] ;
"Jackeline" [shape=box, regular=1, color="pink"] ;
"Abraham" [shape=box, regular=1, color="blue"] ;
"Mona" [shape=box, regular=1, color="pink"] ;
"Patty" [shape=box, regular=1, color="pink"] ;
"Selma" [shape=box, regular=1, color="pink"] ;
"Bart" [shape=box, regular=1, color="blue"] ;
"Lisa" [shape=box, regular=1, color="pink"] ;
"Maggie" [shape=box, regular=1, color="pink"] ;
"Ling" [shape=box, regular=1, color="blue"] ;
a1 [shape=circle,label="",height=0.01,width=0.01];
b1 [shape=circle,label="",height=0.01,width=0.01];
b2 [shape=circle,label="",height=0.01,width=0.01];
b3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Abraham -> a1 -> Mona};
{rank=same; b1 -> b2 -> b3};
{rank=same; Herb; Homer};
a1 -> b2
b1 -> Herb
b3 -> Homer
p1 [shape=circle,label="",height=0.01,width=0.01];
q1 [shape=circle,label="",height=0.01,width=0.01];
q2 [shape=circle,label="",height=0.01,width=0.01];
q3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Homer -> p1 -> Marge};
{rank=same; q1 -> q2 -> q3};
{rank=same; Bart; Lisa; Maggie};
p1 -> q2;
q1 -> Bart;
q2 -> Lisa;
q3 -> Maggie;
x1 [shape=circle,label="",height=0.01,width=0.01];
y1 [shape=circle,label="",height=0.01,width=0.01];
y2 [shape=circle,label="",height=0.01,width=0.01];
y3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Clancy -> x1 -> Jackeline};
{rank=same; y1 -> y2 -> y3};
{rank=same; Marge; Patty; Selma};
{rank=same; Bart; Ling}
x1 -> y2;
y1 -> Marge;
y2 -> Patty;
y3 -> Selma;
Selma -> Ling;
}
ينتج هذا الآن:
لا أفهم تمامًا سبب عملها ، ولكن هنا هي عملية التفكير في التغييرات التي أجريتها.
- وضعت كلانسي/جاكلين قبل إبراهيم/منى أفكر في أنهم كانوا على الجانب الخطأ. هذا غير الصورة ، ولكن لا يزال لم يكن مثاليًا.
- لقد وضعت Homer/Marge أولاً أفكر في أن البرنامج كان عليه أن يفكر في هذه القطع أولاً وربما وضع جميع العقد الأخرى بالنسبة إلى Homer/Marge. هذا ساعد كذلك ، ولكن لا يزال لم يكن مثاليًا.
- كان هيرب لا يزال يسيء وضعه ، لذلك وضعت هيرب أولاً حتى يتمكن Graphviz من التفكير في وضع Herb أولاً.
لقد نجح الأمر ، لكن ما زلت لا أستطيع وضع خوارزمية تضمن الأشجار المتسقة بدون حواف متداخلة. أشعر أن Graphviz يجب أن يقوم بعمل أفضل بدون هذه التلميحات. لا أعرف الخوارزمية المستخدمة ، ولكن إذا نظروا في وظيفة موضوعية لتقليل الحواف المتداخلة أو القضاء عليها ، فيجب أن يكون من الممكن وضع خوارزمية أفضل.
للقيام بذلك في GraphViz مباشرة إلى حد ما ؛ هناك زوجان من أنماط بناء الجملة التي تحتاجها: (1) بناء الجملة لتمثيل الاتصال من الخط إلى الخط ("t"-الوظيفية في مخططاتك أعلاه) ؛ (2) بناء الجملة لفرض الهيكل الهرمي (أي ، العقد من نفس الجيل على نفس المستوى على المحور العمودي). من الأسهل إظهار:
digraph G {
nodesep=0.6;
edge [arrowsize=0.3];
"g1" -> "g2" -> "g3" -> "g4"
{ rank = same;
"g1"; "King"; "ph1"; "Queen";
};
{ rank = same;
"g2"; "ph2"; "ph2L"; "ph2R"; "ph2LL"; "ph2RR"
};
{ rank = same;
"g3"; "ps1"; "ps2"; "pr1"; "pr2"
};
"King" -> "ph1" [arrowsize=0.0];
"ph1" -> "Queen" [arrowsize=0.0];
"ph1" -> "ph2" [arrowsize=0.0];
"ph2LL" -> "ph2L" [arrowsize=0.0];
"ph2L" -> "ph2" [arrowsize=0.0];
"ph2" -> "ph2R" [arrowsize=0.0];
"ph2R" -> "ph2RR" [arrowsize=0.0];
"ph2LL" -> "ps1" [arrowsize=0.0];
"ph2L"-> "pr1" [arrowsize=0.0];
"ph2R" -> "ps2" [arrowsize=0.0];
"ph2RR" -> "pr2" [arrowsize=0.0];
}
سينتج الرمز أعلاه الرسم البياني أدناه (لقد حذفت الرمز الذي استخدمته لتلوين العقد). لقد تركت "دليل" على اليسار (G1-> G2 ....) فقط لأوضح لك كيف فرضت المواقف بين العقد من المرتبة المتساوية ، فربما تريد أن تجعلها غير مرئية في مخططاتك الخاصة. أخيرًا ، العقد التي تحتوي على الملصقات التي تبدأ بـ "PH" هي العقد النائبة لـ "T-Junctions".
أنا هناك تقريبًا ، مستوحاة من استجابة قديمة على قائمة المراسلات GraphViz-Interest و إجابة دوغ.
الرمز التالي:
digraph G {
edge [dir=none];
node [shape=box];
"Abraham" [shape=box, regular=1, color="blue"] ;
"Mona" [shape=box, regular=1, color="pink"] ;
"Clancy" [shape=box, regular=1, color="blue"] ;
"Jackeline" [shape=box, regular=1, color="pink"] ;
"Herb" [shape=box, regular=1, color="blue"] ;
"Homer" [shape=box, regular=1, color="blue"] ;
"Marge" [shape=box, regular=1, color="pink"] ;
"Patty" [shape=box, regular=1, color="pink"] ;
"Selma" [shape=box, regular=1, color="pink"] ;
"Bart" [shape=box, regular=1, color="blue"] ;
"Lisa" [shape=box, regular=1, color="pink"] ;
"Maggie" [shape=box, regular=1, color="pink"] ;
"Ling" [shape=box, regular=1, color="blue"] ;
a1 [shape=circle,label="",height=0.01,width=0.01];
b1 [shape=circle,label="",height=0.01,width=0.01];
b2 [shape=circle,label="",height=0.01,width=0.01];
b3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Abraham -> a1 -> Mona};
{rank=same; b1 -> b2 -> b3};
{rank=same; Herb; Homer};
a1 -> b2
b1 -> Herb
b3 -> Homer
p1 [shape=circle,label="",height=0.01,width=0.01];
q1 [shape=circle,label="",height=0.01,width=0.01];
q2 [shape=circle,label="",height=0.01,width=0.01];
q3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Homer -> p1 -> Marge};
{rank=same; q1 -> q2 -> q3};
{rank=same; Bart; Lisa; Maggie};
p1 -> q2;
q1 -> Bart;
q2 -> Lisa;
q3 -> Maggie;
x1 [shape=circle,label="",height=0.01,width=0.01];
y1 [shape=circle,label="",height=0.01,width=0.01];
y2 [shape=circle,label="",height=0.01,width=0.01];
y3 [shape=circle,label="",height=0.01,width=0.01];
{rank=same; Clancy -> x1 -> Jackeline};
{rank=same; y1 -> y2 -> y3};
{rank=same; Marge; Patty; Selma};
{rank=same; Bart; Ling}
x1 -> y2;
y1 -> Marge;
y2 -> Patty;
y3 -> Selma;
Selma -> Ling;
}
ينتج هذا الآن:
لذا ، تبدو جيدة باستثناء تلك الحافة الغريبة حول هوميروس. إذا تمكنت من إيجاد طريقة لتحريك إبراهيم ، منى والأعشاب إلى الجانب الأيسر من الصورة ، كان لدي صورة محاذاة مثالية.
أي أفكار حول كيفية تحقيق ذلك؟