لجعل بنية Graphviz الهرمية تُقرأ كمخطط تفصيلي متداخل على جهاز Mac، امنح كل عقدة صفًا وإحداثيًا للمسافة البادئة، ثم اعرضها باستخدام neato -n2. يحافظ ذلك على الحواف بين الآباء والأبناء، مع إتاحة التحكم في ترتيب القراءة.
ينشئ هذا الدليل مثالًا من ست عقد ويصدّره إلى ملف PDF. والهدف محدد: عقدة واحدة في كل سطر، وظهور المتحدرات مباشرة أسفل آبائها، وتساوي المسافة البادئة للعقد ذات العمق نفسه. توثّق Graphviz عرض الرسوم ذات المواضع الثابتة عبر خيار سطر الأوامر -n.
لماذا لا تبدو شجرة Graphviz العادية كمخطط تفصيلي؟
تصف البنية الهرمية العلاقات؛ أما المخطط التفصيلي المتداخل فيحدد أيضًا تسلسل القراءة. في هذا المثال، يحتوي الجذر على فرعين، ويجب أن تظهر متحدرات الفرع الأول قبل الفرع الثاني. والترتيب المطلوب هو:
Node R
Node A
Node C
Node D
Node B
Node E
علاقات الرسم هي من الجذر إلى A، ومن الجذر إلى B، ومن A إلى C، ومن A إلى D، ومن B إلى E. لا توجد علاقة من D إلى B لمجرد أن B يظهر في السطر التالي. تعبّر DOT عن الحواف الموجّهة باستخدام العامل ->؛ وتُعد تصريحات العقد وسمات عرضها أجزاء منفصلة من اللغة. راجع مرجع لغة DOT الرسمي.
ينشئ محرّك Graphviz dot رسومات هرمية أو متعددة الطبقات. ويوجّه الحواف في اتجاه مشترك، مع محاولة تقليل التقاطعات وأطوال الحواف. يناسب هذا الهدف مخططًا متشعبًا، لكنه لا يحدد مخططًا تفصيليًا من صف واحد لكل عقدة كالذي يظهر أعلاه. راجع وثائق التخطيط dot.
تعالج عدة سمات مألوفة جزءًا من المشكلة فحسب:
| الإعداد | الغرض الموثّق | ما لا يحسمه |
|---|---|---|
rankdir=LR |
يغيّر اتجاه التخطيط إلى اليسار نحو اليمين | لا يحدد تسلسلًا رأسيًا للمخطط التفصيلي |
rank=same |
يضع عقد الرسم الفرعي على المرتبة نفسها | لا يخصص صفًا مستقلًا في المخطط التفصيلي لكل عقدة |
ordering=out |
يقيّد ظهور الحواف الصادرة من اليسار إلى اليمين حسب ترتيب الإدخال | لا يحدد الإزاحة البادئة وفق العمق وإحداثيات الصفوف |
تتضح هذه الحدود في المراجع الرسمية لكل من rankdir، وrank، وordering. ولترتيب الصفوف المحدد في هذه المقالة، توفر الإحداثيات الصريحة طريقة إنشاء أكثر مباشرة من الجمع بين تلك السمات.
كيف تجهّز Graphviz على جهاز Mac؟
افتح Terminal. إذا كنت تستخدم Homebrew بالفعل، فثبّت Graphviz باستخدام الأمر التالي. تدرج صفحة التنزيل الرسمية لـ Graphviz طريقة التثبيت هذه على Mac:
brew install graphviz
إذا كنت تستخدم MacPorts بدلًا منه، فتدرج صفحة التنزيل نفسها الأمر sudo port install graphviz. استخدم مدير الحزم الذي تعتمد عليه بالفعل. إذا لم يكن أي منهما مثبتًا، فاتبع رابط التثبيت المناسب من تلك الصفحة قبل متابعة هذا الدليل.
تحقق من توفر أداة العرض:
neato -V
يطبع الخيار -V معلومات إصدار Graphviz. احتفظ بالإصدار المذكور عند مقارنة النتائج بين أجهزة الكمبيوتر؛ لا تحتاج إلى رقم إصدار بعينه مما هو مطبوع في هذه المقالة. توثّق Graphviz هذا الخيار في مرجع سطر الأوامر.
كيف تنشئ البنية الهرمية المتداخلة؟
تنشئ كتلة الشل الكاملة التالية مجلد عمل جديدًا وتكتب ملف DOT فيه. شغّلها في Terminal؛ وسيُطبع مسار المجلد عند اكتمالها. يحافظ محدِّد heredoc المقتبس على نص DOT كما هو مكتوب.
outline_dir=$(mktemp -d "$HOME/graphviz-outline.XXXXXX")
if [ -n "$outline_dir" ] && cd "$outline_dir"; then
cat > hierarchy.dot <<'DOT'
digraph Hierarchy {
graph [splines=ortho, bgcolor=white];
node [
shape=box,
width=1.2,
height=0.35,
fixedsize=true,
fontname="Courier",
fontsize=12
];
r [label="Node R", pos="100,300"];
a [label="Node A", pos="136,252"];
c [label="Node C", pos="172,204"];
d [label="Node D", pos="172,156"];
b [label="Node B", pos="136,108"];
e [label="Node E", pos="172,60"];
r -> a;
r -> b;
a -> c;
a -> d;
b -> e;
}
DOT
pwd
fi
ترمّز مواضع العقد المخطط التفصيلي. يتحرك كل صف تالٍ إلى الأسفل بمقدار 48 نقطة، ويتحرك كل عمق إضافي إلى اليمين بمقدار 36 نقطة. هذه الأرقام خيارات توضيحية للتباعد، وليست إعدادات افتراضية في Graphviz. تحدد وثائق pos أن مواضع العقد تشير إلى مراكزها، وأن neato يتعامل مع المواضع على أنها نقاط عند استخدامه مع -n.
| العقدة | العمق | الصف، بدءًا من الصفر | موضع المركز |
|---|---|---|---|
| Node R | 0 | 0 | 100,300 |
| Node A | 1 | 1 | 136,252 |
| Node C | 2 | 2 | 172,204 |
| Node D | 2 | 3 | 172,156 |
| Node B | 1 | 4 | 136,108 |
| Node E | 2 | 5 | 172,60 |
في هذا الإنشاء، قواعد الإحداثيات هي x = 100 + 36 × depth وy = 300 − 48 × row. لاحظ الانتقال من Node D إلى Node B: يتقدم الصف، لكن العمق يتناقص. وهذا الانتقال وحده هو ما يجعل الرسم يُقرأ كمخطط تفصيلي بدلًا من سلسلة.
جميع الصناديق لها الأبعاد نفسها، لذا فإن تساوي إحداثيات المراكز يجعل حوافها اليسرى مصطفّة أيضًا. وتسهل التسميات الاصطناعية المتساوية الطول مقارنة مواضع النص. باستخدام fixedsize=true، تستعمل Graphviz أبعاد العقدة المحددة بدلًا من تكبير الصناديق لتلائم محتوياتها؛ وتُصدر التسميات الأكبر من الصندوق تحذيرًا. راجع مرجع fixedsize.
كيف تعرض النتيجة وتفحصها؟
في جلسة Terminal نفسها ومجلد العمل نفسه، شغّل:
neato -n2 -Tpdf hierarchy.dot -o hierarchy.pdf
هنا، يحافظ -n2 على ترتيب العقد المحدد من دون تعديل لتفادي التداخل، ويحسب مسارات الحواف التي لا تملك مواضع خاصة بها. لذلك تحتاج كل عقدة إلى قيمة pos. يحدد الخياران -Tpdf و-o تنسيق PDF ووجهة الإخراج. توثّق هذه السلوكيات في مرجع سطر الأوامر.
افتح مجلد العمل في Finder ثم افتح hierarchy.pdf. يتطلب إخراج PDF إصدارًا من Graphviz يتضمن عارض Cairo، وفق ما هو محدد في صفحة إخراج PDF الخاصة بـ Graphviz. جرت مراجعة المثال وفق الوثائق، لكن لم يُختبر عرضه هنا لأن Graphviz لم يكن متاحًا في بيئة البحث.
افحص ثلاثة أمور كلًّا على حدة:
- اقرأ من الأعلى إلى الأسفل: ينبغي أن تشغل R وA وC وD وB وE صفوفًا متتالية.
- قارن المسافة البادئة: ينبغي أن تصطف A وB؛ وأن تصطف C وD وE على بُعد خطوة إضافية إلى اليمين.
- تتبّع العلاقات: تصل R بـ A وB؛ وتصل A بـ C وD؛ ويصل B بـ E.
يفحص الأمران الأولان إنشاء الإحداثيات. أما الثالث فيتحقق من الرسم الفعلي. ويساعد إبقاء هذه الفحوص منفصلة على اكتشاف رسم يبدو منظمًا لكنه يتضمن حافة غير صحيحة بين أب وابنه.
هل ستبدو الوصلات تمامًا مثل شجرة متصفح الملفات؟
تُحدد صفوف العقد والمسافات البادئة صراحةً، أما مسارات الوصلات فتحسب تلقائيًا. يطلب المثال splines=ortho، الذي يوجّه الحواف عبر مقاطع متعامدة مع المحاور. وتذكر وثائق Graphviz أيضًا أن هذا التوجيه لا يتعامل مع المنافذ، لذا فإن إضافة منافذ الاتجاهات لا تُعد طريقة موثقة لفرض نمط معين للانحناءات. راجع مرجع splines.
وبالتالي، ينشئ هذا الأسلوب بنية هرمية متداخلة بوصلات قائمة الزوايا تُوجّه تلقائيًا. لكنه لا يحدد مسارًا رأسيًا مشتركًا واحدًا بوصلات فرعية موضوعة بدقة. إذا كان شكل الوصلات هذا ضروريًا، فيلزم إنشاء إضافي بمسارات حواف محددة صراحةً؛ ولا يعبّر splines=ortho وحده عن هذا الشرط.
للحصول على مخطط تفصيلي نظيف بلا وصلات ظاهرة، غيّر إعداد الرسم إلى splines=none ثم أعد العرض. يظل ملف DOT محتويًا على حواف الآباء والأبناء، بينما يحذف العارض خطوطها. هذا خيار عرض موثّق في المرجع نفسه لـ splines.
كيف تعدّل المثال من دون تغيير معناه؟
ابدأ بكتابة ترتيب القراءة المقصود بشكل مستقل عن قائمة الحواف. زُر الأب أولًا، ثم ابنه الأول ومتحدرات ذلك الابن، قبل الانتقال إلى الابن التالي. خصص صفًا لكل عقدة في هذا التسلسل، ثم حدد المسافة البادئة وفق العمق.
على سبيل المثال، لإضافة ابن آخر تحت Node A بعد Node D، أدرجه في تسلسل القراءة قبل Node B. امنحه العمق الثاني، وحرّك الصفوف اللاحقة إلى الأسفل، وأضف حافة من A إلى العقدة الجديدة. لا تتغير علاقات الآباء الحالية لمجرد تغيير أرقام صفوفها.
استخدم التسلسل التشخيصي التالي عندما يبدو إصدار معدّل غير سليم:
- انتشر الرسم في ترتيب مختلف: تأكد من أن الأمر ما زال يستخدم
neato -n2. يعتمد المثال على المواضع المقدمة بدلًا من التخطيط التلقائي المعتاد. - يشير العرض إلى موضع مفقود: تحقق من جميع معرّفات العقد، بما فيها المعرّفات المذكورة في عبارات الحواف فقط. يحتاج كل معرّف إلى تصريح موضع لهذا الأسلوب.
- امتدّت تسمية إلى خارج صندوقها: زد أبعاد الصناديق المشتركة أو اختصر التسمية. لا تتمدد الصناديق ذات الحجم الثابت تلقائيًا.
- تداخلت الصفوف بعد تكبير الصناديق: زد المسافة بين الصفوف. يحافظ وضع العرض المختار على المواضع بدلًا من تصحيح التداخل.
- اتصل فرع بالعقدة الخطأ: صحح عبارة الحافة. لا يمكن لتحريك صندوق إصلاح علاقة غير صحيحة.
تتوافق حالتا الموضع المفقود والتداخل مع سلوك -n2 الموثّق في Graphviz هنا؛ وتتوافق مشكلة التسمية مع سلوك fixedsize الموثّق. وزيادة التباعد هي التعديل التصميمي المقابل لهذا المثال ذي المواضع اليدوية.
اجعل قائمة حواف البنية الهرمية مصدر العلاقات، وجدول الإحداثيات مصدر العرض. في رسم صغير على سطح مكتب Mac، يسهل هذا الفصل صيانة النتيجة: غيّر الحواف عندما تتغير البنية الهرمية، والصفوف عندما يتغير ترتيب القراءة، والتباعد عندما تحتاج التسميات إلى مساحة أكبر.