Results 1 to 2 of 2

Thread: الرسم بلغة السي

  1. #1
    عضو موقوف مؤقتاً Bannd

    Join Date
    Mar 2005
    العمر
    41
    Posts
    493
    Rep Power
    0

    Post الرسم بلغة السي

    مقدمة عن الرسم بالحاسوب بلغة السي Introduction to Computer Graphics in C




    بسم الله الرحمن الرحيم
    لغة السي حجر الأساس في تعلم البرمجة وهي لغة قائمة على البيئة النصيّة، بمعنى لا تحتوي واجهة رسومية GUI مما يتطلب منّا تهيئة بيئة الرسم فيها قبل الشروع في الرسم، فلو قمنا بكتابة أي شيفرة أو دالة بلغة السي لرسم أي شكل هندسي؛ لن نرى نتيجة هذا البرنامج على شاشتنا إلا بعد أن نحدد نوع كرت الشاشة للبرنامج !! والشاشة هنا هي المكونات الصلبة، وهي مختلفة من جهاز لآخر ..
    فمثلاً، محرك SVGA مخصص لكروت VGA التي تسمح بعرض 256 لون مختلفة، وتدعم أكثر أنماط الـ256 لون انتشاراً، والجدول التالي يعطينا بعض الأنماط والذاكرة التي تحتاجها وكروت الشاشة التي تستخدمها:
    الكروت التي تستخدمه Who uses it الذاكرة Memory الوصف Description النمط Mode
    Standard VGA and MCGA 64K 320x200x256 0
    Some Super VGAs 256K 640x400x256 1
    Most Super VGAs 512K 640x480x256 2
    Some Super VGAs 512K/1M 800x600x256 3
    Some Super VGAs 1M 1024x768x256 4
    Some Super VGAs 2M 1280x1024x256 5
    وهذا المحرك يدعم أكثر أوامر الـGraphics في اللغة، وخصوصاً أوامر بورلاند القياسية standard Borland graphics commands وبالذات فيما يتعلق بالرسم Borland's GRAPH،وقد صمم في الأصل للتعامل مع كروت العرض CGA و EGA.
    وبعد هذه المقدمة البسيطة يبرز لنا سؤالان:
    السؤال الأول: ماهو شكل بيئة الجرافيكس الممثلة للشاشة في لغة السي؟ أو بمعنى آخر كيف تمثل لغة السي الشاشة وتتعامل معها للرسم عليها؟
    والسؤال الثاني: كيف لنا أن نقدم تعريف بنوع كرت شاشة الجهاز لبرنامجنا وأنواع كروت الشاشة كثيرة جداً ومختلفة من جهاز لآخر؟
    مقدمة عن الرسم بالحاسوب بلغة السي Introduction to Computer Graphics in C:
    كي نبدأ بالرسم في السي، لابد أولاً من أن نفهم نظام محاور الإحداثيات في هذه اللغة!
    من المعلوم لدينا أن الشاشة ما هي إلا نقط تعرّف كل نقطة بالبكسل Pixel، النقطة الواقعة في الركن الشمالي الغربي (الركن العلوي الأيسر) في الشاشة تمثل نقطة الأصل (0،0) في لغة السي كما يوضح الفلاش التالي:
    حيث أن كلاً من الدالتين ( )getmaxx و( )getmaxy عبارة عن دوال جاهزة في اللغة تقوم بحساب أقصى قيمة للبكسلان اللذان يمثلان أبعاد الشاشة.
    وبهذا نكون أجبنا على التساؤل الأول ويبقى التساؤل الثاني:
    لتهيئة بيئة الجرافيكس؛ لغة السي سهلت علينا الموضوع، فببساطة يوجد بها دالة جاهزة تقوم بهذا الغرض، اسم هذه الدالة initgraph:
    void far initgraph(int far *graphdriver, int far *graphmode, char far *pathtodriver);
    ولها ثلاث حقول Argument هي:
    1. GraphDriver نحدد في هذا الحقل نوع كرت الشاشة.
    2. GraphMode نحدد في هذا الحقل نمط كرت الشاشة.
    3. Directory نحدد في هذا الحقل المسار الذي يوجد فيه كمبايلر الجرافيكس على جهازنا.
    ولمعرفة نوع ونمط كرت شاشاتك، أمامك عدة خيارات:
    • بإمكانك أن تضعه كقيمة لهذه الحقول إن كنت تعرفه مسبقاً.
    • في بورلاند: بإمكانك وضع قيمة حقل GraphDriver تساوي صفر كي يقوم أتوماتيكياً باستخدام دالة توفرها اللغة كي تكشف لك نوع ونمط كرت الشاشة، هذه الدالة هي:
    void far detectgraph (int far *graphdriver, int far *graphmode);
    • كحالة عامة: بإمكانك استخدام كلمة عامة كقيمة للمتغيرGraphDriver كي تعمل مع جميع الاجهزة ومختلف أنواع الكروت، هذه القيمة هي الأمر DETECT، وهي التي سنعتمدها في برامجنا إن شاء الله كما يوضح الـcode التالي:

    void initialize_graph(void)
    {
    /* select a driver and mode that supports */
    /* for example: int gdriver = EGA, gmode = EGAHI; */
    int gdriver = DETECT, gmode;
    initgraph(&gdriver,&gmode,"\\tc2");
    }
    وبعد الرسم على الشاشة، لابد من إغلاق بيئة الرسم، وفرت اللغة كذلك دالة لهذا الغرض، اسمها ( )closegraph وليس لها حقول:
    void close_graph(void)
    {
    /* clean up */
    closegraph();
    }
    أما مكتبات السي التي نحتاجها للرسم، فهي التالية:
    #include "stdio.h"
    #include "dos.h"
    #include "graphics.h"
    #include "stdlib.h"
    #include "io.h"
    #include "conio.h"
    #include "ctype.h"
    وبإمكانك مراجعة الدرس التالي لمعرفة محتويات كل مكتبة: http://www.c4arab.com/showlesson.php?lesid=1515
    وبذلك نكون قد تعرفنا على بيئة الرسم كيفية تهيئتها وكيفية إغلاقها، تذكر هاتان الدالتان Functions جيداً فسنستخدمها مع كل code للرسم بالحاسوب في السي، سنتعلم سوياً في الرسم بالحاسوب التالي إن شاء الله:
    • color control & colors in C نظم الألوان والألوان في السي.
    • Drawing Lines, Rectangles, & Circle رسم الخطوط، المستطيلات والدوائر.
    • Drawing PI-Charts التخطيطات البيانية.
    • 2D Geometric Transformations: التحويلات الهندسية ثنائية الأبعاد:
    o Translation الإزاحة.
    o Rotation الدوران.
    o Scaling إعادة الأحجام.
    o Reflection الإنعكاس.


    رسم الخطوط في السي Drawing Lines in C:
    يوجد في لغة السي دالة جاهزة لرسم الخط، فمن المعروف أننا نرسم الخط بتحديد إحداثيات نقطتين عليه، إحدثيات هذه النقاط لابد من أن تكون أعداد صحيحة فلا يوجد شئ اسمه "بكسل ونصف" على الشاشة نقره لتكبير أو تصغير الصورة ونقرتين لعرض الصورة في صفحة مستقلة بحجمها الطبيعي
    هذه الدالة بكل بساطة هي:
    line(int x1 , int y1 , int x2 , int y2);
    حيث أن (x1, y1) هي إحداثيات النقطة الأولى، و(x2, y2) هي إحداثيات النقطة الثانية.
    والنتيجة ستكون رسم خط بين هاتين النقطتين سواء كان الميلان موجب أو سالب كما توضح الصورتين التاليتين:



    ميل سالب ميل موجب
    بعد رؤيتنا للتنيجة، سيتبادر إلى أذهاننا سؤالين مباشرة:
    1. لماذا في أي رسم كمبيوتري يظهر الخط مع بعض الإنكسارات على امتداده؟
    2. كيف تعمل هذه الدالة line وتتعامل مع الشاشة؟
    الإجابة السؤال الأول يتكفل بها مفهوم وجود الـPixels على الشاشة، حيث أن الشاشة تتكون من ذرات مرتبة في أعمدة وصفوف تسمى Pixels، والخط ماهو إلا امتداد لسلسلة مواضع النقط Pixels على الشاشة كما يوضح الشكل التالي:

    ولمعرفة كيفية عمل الدالة line وتعاملها مع الشاشة سننشئ معاً دالة جديدة لها نفس عمل هذه الدالة بعد أن نثبت النظرية التي سنستخدمها! حيث أنه يوجد عدة نظريات لرسم خط على الشاشة Lines-Drawing Algorithms منها على سبيل المثال:
    • خوارزم محلل التفاوت الرقمي Digital Differential Analyzer (DDA) Algorithm.
    • خوارزم العالم بريزنهام Bresenham's Algorithm.
    سنكتفي بشرح الخوارزم الأول وإثباته إن شاء الله، مع العلم أن كلا الخوازمين يعتمدون على المفاهيم الرياضية ومعادلات الخاصة بالخط المستقيم، فمن المعلوم أن معادلة الخط المستقيم تعطى من:
    y = m * x + b
    حيث أن m تمثل ميل الخط المستقيم، وb تمثل الجزء المقطوع من محور الصادات! وبتحديد نقطتي نهاية الخط المستقيم هما (x1, y1) و(x2, y2) مثلاً، نستطيع تحديد قيمة كلاً من الـm وb كالتالي:

    ومن المعادلة الأولى نستنتج أن:
    ------(1) ∆y = m * ∆x
    ------(2) ∆x = ∆y / m
    حيث أن أكبر قيمة ممكنة للميل m على المحور السيني هي الواحد:
    |m| < 1
    وبالتعويض في المعادلة (1) أو (2) نحصل على:
    ∆y = ∆x
    هذا في المستوى الكارتيزي أما على الشاشة فإن المستوى يسمى Raster ويعني خطوط المسح المجالية، ويرسم الخط بواسطة رسم النقاط التي تسمى Pixels.
    خوارزم محلل التفاوت الرقمي Digital Differential Analyzer (DDA) Algorithm:
    هذا الخوارزم يرسم pixel ثم يختار أفضل pixel قريبة لرسم النقطة التالية.. وهكذا إلى أن ينتهي من رسم الخط. حيث يعتمد فحص الخط في هذا الخوارزم على حساب كلاً من فرق السينات (∆x) أو فرق الصادات (∆y) وتثبيت أحدهما عند رسم أي pixel في الخط حتى نحصل على الميل المطلوب للخط مع المحافظة على انسيابه ونعومته وعدم إظهار التكسر فيه قدر الإمكان، كيف ذلك؟
    العرض التالي يوضح الفكرة التي سنثبتها رياضياً بعد قليل إن شاء الله:
    والإثبات كما رأينا له مرحلتين:
    • عند تثبيت الزيادة على المحور السيني أي ∆x = 1 فإننا من المعادلة (1) أو (2) نحصل على:
    ∆y = m
    y2 -y1 = m
    y2 = y1 + m
    وكقاعدة عامة:
    yk+1 = yk + m
    إذن:
    x Increment = 1
    y Increment = m
    • عند تثبيت الزيادة على المحور الصادي أي أن ∆y = 1 فإننا من المعادلة (1) أو (2) نحصل على:
    ∆x = 1/m
    x2 - x1 = 1/m
    x2 = x1 + 1/m
    وكقاعدة عامة:
    xk+1 = xk + 1/m
    إذن:
    x Increment = 1/m
    y Increment = 1
    هذا هو الإثبات ببساطة، وقد نتسائل الآن: على ماذا نعتمد؟ هل نعتمد على تثبيت الزيادة على المحور السيني أم الصادي؟!
    إن النقطتين اللتين يصل الخط بينهما هما الفيصل هنا:
    • فإن كانت |∆x| > |∆y| نعتمد ∆x كخطوة من pixel إلى pixel أخرى.
    • وإن كانت |∆y| > |∆x| نعتمد ∆y كخطوة من pixel إلى pixel أخرى.
    والآن، لنكتب معاً الـFunction بلغة السي والتي تمثل هذا السيناريو، حيث أننا سنحتاج فيها إلى معرفة نقطتي نهاية الخط فقط:
    #include "stdio.h"
    #include "dos.h"
    #include "graphics.h"
    #include "stdlib.h"
    #include "io.h"
    #include "conio.h"
    #define ROUND(a) ((int) (a+0.5))

    void lineDDA (int xa, int ya, int xb, int yb)
    {
    int dx = xb - xa, dy = yb - ya, steps, k;
    float xincrement, yincrement, x = xa, y = ya;

    if ( abs(dx) > abs(dy) )
    steps = abs(dx);
    else
    steps = abs(dy);
    xincrement = dx/(float) steps;
    yincrement = dy/(float) steps;
    // to plot first pixel
    setPixel( ROUND(x), ROUND(y) );

    // to plot other pixels
    for (k=0;k<steps;k++){
    x += xincrement;
    y += yincrement;
    setPixel ( ROUND(x), ROUND(y) );
    getche();
    }
    getche();
    }// End of LineDDA Function


    setPixel(x, y)
    int x,y;
    {
    putpixel(x, y, 4);
    }

    void main()
    {
    int graphdriver=DETECT, graphmode;
    int x1, y1, x2, y2;
    // Enter two endpoints
    printf("X1="); scanf("%d",&x1);
    printf("\nY1="); scanf("%d",&y1);
    printf("\nX2="); scanf("%d",&x2);
    printf("\nY2="); scanf("%d",&y2);
    initgraph(&graphdriver, &graphmode, "\\tc2");
    setpalette(0, 4);
    setbkcolor(0);
    getche();
    lineDDA(x1, y1, x2, y2);
    }// End of main
    دالة التقريب ( (ROUND(a) ( (int) (a+0.5: وظيفتها تقريب القيمة المرسلة إليها (غالباً تمثل موضع pixel على الشاشة) إلى عدد صحيح، فلا يوجد شئ يسمى بكسل ونصف على الشاشة، وكما تلاحظون من تعريفها فإنها تضيف لأي عدد يرسل إليها 0.5 ثم تأخذ القيمة الصحيحة int، فإن كان العدد صحيحاً منذ البداية لم يتأثر بإضافة النصف إليه، وإن كان كسرياً من البداية فإنه سيصبح صحيحاً بعد إضافة النصف إليه.
    هذا هو خوارزم DDA ، وهذه هي طرق رسم الخط المستقيم في السي،، أرجو من الله أن يكون الدرس واضحاً .. والسلام عليكم نقره لتكبير أو تصغير الصورة ونقرتين لعرض الصورة في صفحة مستقلة بحجمها الطبيعي

    --------------------------------------------------------------------------------

  2. #2

    وائل عبدالله's Avatar
    Join Date
    Sep 2003
    Location
    usa
    العمر
    42
    Posts
    7,125
    Rep Power
    426
    طبعاً هذا الدرس مفيد للذين يبدؤن بالاشكال في السي بلس بلس
    مشرف سابق في شباب اليمن...

    تريد موقع قراني (تفصل من هنا)


    http://www.quran4u.co


    نقره لتكبير أو تصغير الصورة ونقرتين لعرض الصورة في صفحة مستقلة بحجمها الطبيعي

    ادخل على مكتبة صور راح تخدربك

    www.funize.net


Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. فن الرسم على اليد
    By ألاسير in forum ملتقى الصور
    Replies: 12
    Last Post: 31-12-2009, 07:48 PM
  2. فن الرسم بالماء !!!
    By إحساس إنسان in forum ملتقى الصور
    Replies: 9
    Last Post: 07-03-2009, 06:29 PM
  3. متى بصير مشرف يا الوحيشي مثلك ؟ ( امزح امزح موضوع ترحيبي )
    By صقر الوحيشي in forum ملتقى الاستراحة والترحيب بالأعضاء
    Replies: 19
    Last Post: 14-09-2006, 05:38 PM
  4. Replies: 2
    Last Post: 14-02-2006, 05:27 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •