رياضيات
برمجية!
وأنا
أعمل في برنامج مصمم الرسوم التخطيطية Diagram Designer، لجأت إلى علم حساب المثلثات Trigonometry أكثر من مرة، وهذا شيء منطقي لأن البرنامج رسومي في طبعه.
إحدى
هذه المرات كانت تخص رسم خط مستقيم للتوصيل بين شكلين.. هذا أمر بسيط طبعا وليس فيه
حسابات خاصة، لكني أردت رسم خط آخر مواز لخط التوصيل، يظهر حينما يكون الخط محددا Selected.. بشرط أن تكون المسافة بين الخطين 5
نقاط في كل من الاتجاه الفعلي للخط والاتجاه العمودي عليه (انظر الصورة).
ونظرا
لأن الخط لا يكون رأسيا أو أفقيا دائما، وإنما يمكن أن يميل بأي زاوية على المحور
الأفقي (الزاوية الحمراء في الصورة)، فقد استلزم هذا الأمر بعض عمليات حساب
المثلثات، لمعرفة الإزاحة الأفقية والرأسية المطلوبة لنقطة بداية الخط الثاني.
مبدئيا
يمكن حساب زاوية ميل الخط عن المحور الأفقي كالتالي:
Dim
A = Math.Atan((Y2-Y1)/(X2-X1))
حيث
X1,Y1 هما إحداثيات نقطة
بداية الخط، و X2,Y2 هما إحداثيات
نقطة نهايته، وناتج قسمة المسافة الرأسية بين النقطتين على المسافة الأفقية بينهما
يعطي ميل الخط (ظل الزاوية)، وقد استخدمنا الدالة Atan للحصول على الزاوية من هذا الميل، مع ملاحظة أنها ستكون بالتقدير
الدائري Rad.
الآن
نريد حساب الإزاحة الأفقية dx (الخط
P1-P4 في الصورة) والإزاحة
الرأسية dy (الخط
P4-P3 في الصورة)،
لتحديد موضع بداية الخط الثاني.. بدراسة المسألة الموضحة في الصورة، يتضح أن الخط P1-P3 الواصل بين نقطي بداية الخطين هو وتر المثلث القائم
متساوي الضلعين الناتج من الإزاحة 5 نقاط في كلا الاتجاهين، إذن فطوله = (5 × جذر
2) أو (جذر 50).
هذا
الخط يميل عن الخط الأفقي بزاوية مقدارها A+45.. الزاوية 45 هي الزاوية الناتجة عن المثلث القائم متساوي الضلعين
الذي ذكرته سابقا (مظللة بالأخضر في الصورة).. لاحظ أن الزاوية المحصورة بين
الزاوية الحمراء والزاوية الخضراء عند النقطة P3 قيمتها هي أيضا 45 درجة، لأنها تشكل مع الزاوية الخضراء زاوية
قائمة.
ومن
الضروري تحويل الزاوية 45 إلى التقدير الدائري (بضربها في النسبة التقريبية
والقسمة على 180)، قبل جمعها على الزاوية A:
Dim
A2 = A + 45 * Math.PI / 180
الآن
صار من السهل حساب الإزاحة الأفقية والرأسية (ضلعا المثلث الأصفر في الصورة)، بضرب
طول الوتر في جيب تمام الزاوية A2 وجيب
الزاوية A2 على
الترتيب:
Dim
L = Math.Sqrt(50)
Dim
dx = Math.Cos(A2) * L
Dim
dy = Math.Sin(A2) * L
وقد
وصلت لصيغة أخرى لحل نفس هذه المسألة، لكن هذه هي الأبسط.. وقد استخدمت الإزاحة
والأفقية والرأسية مع الخاصية Margin في WPF لإزاحة خط التحديد، وكل شيء يعمل على
ما يرام، ويظهر خط التحديد على مسافة ثابتة دائما من خط التوصيل مهما اختلفت زاوية
ميله.
ملحوظة
لمن يرتعبون من الرياضيات:
لم
أستخدم في هذه الحسابات أكثر من أساسيات حساب المثلثات التي درسناها جميعا في
المرحلتين الإعدادية والثانوية، مما أعاد لي ذكريات جميلة، لأني كنت أعتبر
الرياضيات (واللغة العربية) متعتي وسط مستنقع المواد المقرفة المفروضة عليّ في
التعليم.. ويهمني هنا أن أوجه الشكر أستاذي الفاضل الخلوق الذي ساهم في جعل
الرياضيات متعة بالنسبة لي: أ. عاطف الهدبي، جزاه الله خيرا وأطال في عمره.
ملحوظة
أخرى:
العلاقة
بين الرياضيات والبرمجة علاقة وطيدة، وهناك رياضيات متقدمة تدخل في البرمجة
الرسومية والمجسمات.. على سبيل المثال، كنت على وشك استخدام خوارزمية B-spline للحصول على الحد المحيط بكل شكل في
نفس هذا البرنامج لوضع نقاط توصيل عليه (لاحظوا أني سمحت للمستخدم بتعريف الأشكال،
لهذا لا أعرف ماذا ستكون مسبقا).. لكني وجدت هذا معقدا جدا، وفضلت حلا آخر أسهل وأكثر
عملية، استخدمت فيه خوارزمية شبيهة بخوارزمية البحث الثنائي Binary
Search للبحث عن أقرب نقطة على حد الشكل (ليس هذا موضع شرح هذا.. سأشرحه
بإذن الله في الكتاب التالي).
كما
أن برامج معالجة الصور والصوت تستخدم الرياضيات وقوانين علم الإشارات Signals، وهي وبرامج معالجة اللغات الطبيعية
والذكاء الصناعي، تستخدم طرقا إحصائية ورياضيات متقدمة، لهذا تحتاج هذه البرامج
إلى مهندسين أكثر مما تحتاج إلى مبرمجين.. ولعلي هنا أيضا أوجه الشكر لأستاذي
وصديقي د. م. محمد عطية العربي، الذي تعرفت من خلال عمله في هذه المجالات على بعض هذه
التقنيات، وألجأ إليه دائما بالسؤال عن أي خوارزمية متقدمة قد أحتاجها (مثل B-spline).