>> الصفحة الرئيسية >> دروس متقدمة >> منحنيات bezier + مثال برمجي

الأقسام الرئيسية

 التنصيب والاعداد التنصيب والاعداد
 دروس متقدمة دروس متقدمة
 سلسلة دروس للمبتدئين سلسلة دروس للمبتدئين
 اساسيات لغة سي++ اساسيات لغة سي++
 مقالات ZetCode مقالات ZetCode
 

جديد الدروس

 الوحدة QtUiTools (واجهة المستخدم ديناميكية التوليد)
التاريخ 04/07/2009 الوحدة QtUiTools (واجهة المستخدم ديناميكية التوليد)
 Qt and Phonon
التاريخ 04/07/2009 Qt and Phonon
 تتمة الرسائل ومربعات الحوار في qt
التاريخ 04/07/2009 تتمة الرسائل ومربعات الحوار في qt
 مدخل الى xml في Qt
التاريخ 04/07/2009 مدخل الى xml في Qt
 الإدخال والإخراج لبيانات الفئات
التاريخ 04/07/2009 الإدخال والإخراج لبيانات الفئات
 

منحنيات bezier + مثال برمجي

مقدمة :
بعيدا عن نشأة هذه الطرق من المنحنيات الحرة فإننا في الحقيقة بحاجة الى ان نعرف كيف نتعامل مع هذه المنحنيات الحرة ليكون لك دخرا في التصميم التي في الغالب انك لن تحتاج ان تتعامل مع هذه الأنواع من المنحنيات رياضيا ولكن برمجيا فإنه لاغنى عنك عن تعلم هذه المنحنيات الحرة بإسلوبها الرياضي خاصة لمبرمجي الألعاب او او البرامج الهندسية او ..... .
وبما ان هذه المنحنيات اصبحت متعارف عليها في جميع مكاتب التصميم ولغات البرمجة وبرامج التصميم من ثنائي البعد وثلاثي البعد أرتأيت ان اشرح هذا الإسلوب من المنحنيات الحرة ليكون اول مقال عربي يتحدث عن هذا الموضوع .

منحنيات بيزير :
قامت هذه المنحنيات على مبدأ ان هناك سلسلة من النقاط .
نقطتين تحددان البداية والنهاية وتسمى النقاط المحددة حيث انهما لوحدهما لا يشكلان أي انحناءة سوى خط مستقيم من نقطة البداية الى النهاية. ثم يتوسطهم نقاط تدعى بنقاط التحكم لأنها هي من تتحكم بشكل المنحى وفق معادلات بيزير.

انظر الرسم :


فالنقاط P0 و P3 تعتبر محددتا المنحنى والنقاط P1 و P2 تسمى نقاط التحكم .
وتسمى هذه المنحنيات بمنحنيات الدرجة الثالثة لأنها تتكون من أربعة نقاط ولو تأملنا في معادلتها عندما تمر بنا سنجد انها من الدرجة الثالثة أيضا وكذلك منحنيات ال ثلاث نقاط هي منحنيات درجة ثانية وهكذا وفق القاعدة ن-1 حيث ن = عدد نقاط منحنى بيزير


كيف يرسم الحاسب هذه المنحنيات ؟
الفكرة هي استخدام " elegant recursive procedure" الإجرار التكراري .

فمثلا عند رسم الخط المستقيم :
1- تلوين البكسلات عند نقاط البداية والنهاية . .
2- تلوين النقطة في الوسط .
3- تقسيم الخط الى نصفين .
4- تنفيذ الخطوتين 2 و 3 على كل من النصفين .


الى ان لايمكن تمييز البكسات في الخط .
وعلى هذا المبدأ يقوم الحاسب برسم منحنيات بيريز .

فمثلا لو لدينا النقاط P0, P1/3, P2/3, P1 حيث النقاط المحددة هنا هي P0 و P1
فإنه يتم تلوين كل من النقاط المحدد كخطوة أولى ومن ثم تحديد الوسط عن طريق :

P1/6 = في الوسط بين P0 وP1/3
P5/6 = في الوسط بين P2/3 و P1
Q = في الوسط بين P1/3 و P2/3
P2/6 = في الوسط بين P1/6 و Q
P4/6 = في الوسط بين Q و P5/6
P1/2 = في الوسط بين P2/6 و P4/6


كما في الشكل التالي :


لنرسم فوقها نقطة الوسط.
ونقسم الشكل الى نصفين الأول P0 و P1/6 و P2/6 و P1/2 .
والثاني P1/2 و P4/6 و P5/6 وينتهي ب P1 .
لنقوم بعد ذلك بتكرار الخطوتين الثانية الثالثة في النصفين الى ان نحصل على منحنى يسمى منحنى بيزير .


التعامل مع منحنى بيزير رياضيا :
هذا ما اردت ان نصل اليه لأن الخطوة السابقة أصبحت غير مستخدمة فجميع برامج التصميم واغلب لغات ومكتبات البرمجة توفر دوال لرسمها دون الحاجة لإتباع الخوارزمية السابقة .
ويمكننا تعريف معادلتها في صيغة عامة حيث درجة منحنى بيزير = n والنقاط من , P1, P0 الى Pn
اذا :

مفكوكة نظرية ذات الحدين B(t)=((1-t)+t)^n حيث يضرب كل حد من حدود مفكوكتها ب P0 الى Pn ابتداء من حدها الأول .

ومنه:


حيث Xn-X0) t =(X-X0)/(
ومنه فإن قيمته تنحصر بين [0,1]
ومنه فإن Pn=Yn
او اذا تم تستبدال X ب Y في t فإن Pn=Xn
ومن هذه المعادلات نستنتج ان :
P(0) = y0
P(n) = yn

مثال : اوجد مفكوكة منحنى بيزير من الدرجة الثالثة .

((1-t)+t)^3=((1-t)^3)+(3(1-t)^2 * t )+(3(1-t) * t^2)+ (t^3)

ومنه فإن معادلة منحنى بيزير من الدرجة الثالثة هي التالي:

((1-t)^3)P0+(3(1-t)^2 * t )P1+(3(1-t) * t^2)P2+ (t^3)P3 B(t)= لكل t=[0,1]

ومن خصائص منحنيات بيزير
ان ميل مماس المنحنى عند نقطة P0 =V0= (Y1-Y0)/(X1-X0)
ومنه V0 Y1=Y0+(X1-X0)*
وكذلك ان ميل مماس المنحنى عند نقطة Pn =Vn= (Yn-Yn-1)/(Xn-Xn-1)
ومنهVn Yn-1=Yn-(Xn-Xn-1)* .
حيث درجة منحنى بيزير= n


محاكاة منحنيات مشهورة بإستخدام منحنيات بيزير :
للمعلومية ان المحاكاة هنا لايعني تطابق الرسم بنسبة 100% ولكن سوف تكون هناك إختلافات بسيطة لا تؤثر على الشكل العمومي للرسم .
ومن أحد أشهر أساليب المحاكاة تجزئة النقاط الى مسافات X متساوية لنحدد فيما بعد Y لكل نقطة بمعادلات تفاضلية .
وكلما زادت عدد النقاط في المحاكاة فإن دقة المنحنى تزداد ولكن كما ذكرنا سابقا فإن الإختلافات سوف تكون بسيطة جدا بحيث انها لا تغير على الشكل العام للمنحنى

مثال(1)
قم بمحاكاة قطع مكافئ من النقطة X=-1 الى X=1 ؟

فلو أكتفينا بالرسم بنقطتين تحكم + نقطتي التحديد فإن الحل:
معادلة القطع المكافئ الذي محوره y واتجاهه للأعلى هو X^2=4aY و a=1/4 بإفتراض
أن نقاط التحديد P0(-1,1) و P3(1,1)
المسافة بين X0,X3 = 2 .
ومنه نقسم المنحنى الى ثلاثة أقسام على X لتحديد نقاط التحكم على الإحداثي X وينتج ان المسافة بين كل نقطة ونقطة هو 2/3 اذا النقاط على المحورX هي X0=-1 ,X1=-1/3 ,X2=1/3 ,X3=1
ووفقا للمعادلتين
V0 Y1=Y0+(X1-X0)* و Vn Yn-1=Yn-(Xn-Xn-1)*
فإنه بالإمكان تحديد كل من النقطتين Y1 و Yn-1 .
ولكن علينا ايجاد dy/dx = 2X/4a
ومنه اذا علمنا مسبقا ان a=1/4 اذا dy/dx= 2X .
اذا الممال عند X0=-2 و عند X3=2
اذا=-1/3 (Y1=1+2/3*(-2
و
Y2=1-2/3*2=-1/3
اذا وبما انه وجدنا أبعاد نقاط التحكم + توفر ابعاد نقاط التحديد فإنه يمكن رسم الشكل وفق النقاط التالية
P0(-1,1) و P3(1,1) و P1(-1/3,-1/3) و P2(1/3,-1/3)

[/b]



وإليكم بعض المراجع في المرفقات للأسف باللغة الإنجليزية فقط:

مرجع لمنحنيات بيزير الدرجة الثالثة وهي الأكثر استخداما
http://www.qt-ar.org/community/download/file.php?mode=view&id=12

مرجع آخر جميل
http://www.qt-ar.org/community/download/file.php?mode=view&id=11

مرجع لمنحنيات بيزير ثلاثية الأبعاد
http://www.qt-ar.org/community/download/file.php?mode=view&id=10


مثال برمجي:

ومثال برمجي عليه فإني قمت بعمل هذا البريمج لمنحنى بيزير من الدرجة الثالثة :




وهي تحتوي على الشيفرات التالية


  1. #ifndef __BEZIER_H__
  2. #define __BEZIER_H__
  3.  
  4. #include<QtGui>
  5.  
  6. class bezier:public QGraphicsView{
  7. Q_OBJECT
  8. //==============================================
  9. public:
  10. bezier(QWidget* parent=0);
  11. void drawCurve();
  12. void drawLines();
  13. //==============================================
  14. protected:
  15. void timerEvent ( QTimerEvent * event ) ;
  16. //========================================
  17. private:
  18. bool check;
  19. //=====================================
  20. };
  21.  
  22. #endif // __BEZIER_H__

============================================
  1. #include "bezier.h"
  2.  
  3. bezier::bezier(QWidget* parent):QGraphicsView(parent){
  4. scene=new QGraphicsScene;
  5. scene->setSceneRect(0,0,500,500);
  6. setScene(scene);
  7. scene->setBackgroundBrush(QBrush(Qt::black));
  8. for(int m=0;m<=3;m++){
  9. if(m<2){
  10. ellipse=scene->addEllipse(0,0,6,6,Qt::DotLine,QColor(Qt::white));
  11. ellipse->setFlag(QGraphicsItem::ItemIsMovable,1);
  12. ellipse->moveBy((m+1)*150,200);
  13. ellipse->setCursor(Qt::SizeAllCursor);
  14. points<<ellipse;
  15. }
  16. else{
  17. ellipse=scene->addEllipse(0,0,6,6,Qt::DotLine,QColor(Qt::white));
  18. ellipse->setFlag(QGraphicsItem::ItemIsMovable,1);
  19. ellipse->moveBy((m-1)*200,400);
  20. ellipse->setCursor(Qt::SizeAllCursor);
  21. points<<ellipse;
  22. }
  23. }
  24. startTimer(5);
  25. scene->addItem(&curve);
  26. drawCurve();
  27. drawLines();
  28. }
  29. //====================================
  30. void bezier::drawCurve(){
  31. path.moveTo(points[0]->x()+3,points[0]->y()+3);
  32. path.cubicTo(points[2]->x()+3,points[2]->y()+3,points[3]->x()+3,points[3]->y()+3,points[1]->x()+3,points[1]->y()+3);
  33. curve.setPath(path);
  34. curve.setPen(QPen(Qt::darkGreen,4));
  35. }
  36. //===============================================
  37. void bezier::drawLines(){
  38. if(lines.count()<3){
  39. lines<<scene->addLine(points[0]->x()+3,points[0]->y()+3,points[1]->x()+3,points[1]->y()+3,QPen(Qt::white,1,Qt::DotLine));
  40. lines<<scene->addLine(points[0]->x()+3,points[0]->y()+3,points[2]->x()+3,points[2]->y()+3,QPen(Qt::white,1,Qt::DotLine));
  41. lines<<scene->addLine(points[3]->x()+3,points[3]->y()+3,points[1]->x()+3,points[1]->y()+3,QPen(Qt::white,1,Qt::DotLine));
  42. lines<<scene->addLine(points[2]->x()+3,points[2]->y()+3,points[3]->x()+3,points[3]->y()+3,QPen(Qt::white,1,Qt::DotLine));
  43. }
  44. else{
  45. lines[0]->setLine(points[0]->x()+3,points[0]->y()+3,points[1]->x()+3,points[1]->y()+3);
  46. lines[1]->setLine(points[0]->x()+3,points[0]->y()+3,points[2]->x()+3,points[2]->y()+3);
  47. lines[2]->setLine(points[3]->x()+3,points[3]->y()+3,points[1]->x()+3,points[1]->y()+3);
  48. lines[3]->setLine(points[2]->x()+3,points[2]->y()+3,points[3]->x()+3,points[3]->y()+3);
  49. }
  50. }
  51. //===========================================
  52. void bezier::timerEvent ( QTimerEvent * event ) {
  53. drawLines();
  54. drawCurve();
  55. }


ومجلد الشفرات المصدرية :
الكود

إسم الكاتب تاريخ الإضافة التقييم / المقيمين زيارات الدرس
مصفوفة 20/09/2008 11 / 2 1894

الأكثر زيارة

 دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير QDevelop
الزيارات 4284 دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير QDevelop
 اعداد وتنصيب Qt
الزيارات 4071 اعداد وتنصيب Qt
 التطوير السريع للتطبيقات Rapid Application Development
الزيارات 3762 التطوير السريع للتطبيقات Rapid Application Development
 دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير Eclipse
الزيارات 3747 دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير Eclipse
 C++ In a Nutshell
الزيارات 3154 C++ In a Nutshell
 

الأكثر تصويتـا

 اعداد وتنصيب Qt
نتيجة التصويت 41 من 6 شخص اعداد وتنصيب Qt
 الدرس الاول : كتابة اول برنامج
نتيجة التصويت 41 من 6 شخص الدرس الاول : كتابة اول برنامج
 تخطيط البرامج Program Layout
نتيجة التصويت 40 من 6 شخص تخطيط البرامج Program Layout
 دوال المستوى العالي لبرمجة تطبيقات متعددة المسالك
نتيجة التصويت 30 من 3 شخص دوال المستوى العالي لبرمجة تطبيقات متعددة المسالك
 التطوير السريع للتطبيقات Rapid Application Development
نتيجة التصويت 30 من 5 شخص التطوير السريع للتطبيقات Rapid Application Development
 
 

سكربت story-script v1 برمجة bwady.com تطوير SudaNix