حصاة اللبن
اهلا وسهلا بك في منتدى حصاة اللبن انت زائر جديد في حصاة اللبن ندعوك للتسجيل في المنتدى
منتدى حصاة اللبن
hasah.yoo7.com ^_^
حصاة اللبن
اهلا وسهلا بك في منتدى حصاة اللبن انت زائر جديد في حصاة اللبن ندعوك للتسجيل في المنتدى
منتدى حصاة اللبن
hasah.yoo7.com ^_^
حصاة اللبن
هل تريد التفاعل مع هذه المساهمة؟ كل ما عليك هو إنشاء حساب جديد ببضع خطوات أو تسجيل الدخول للمتابعة.

حصاة اللبن

اهلا وسهلا بكم في منتدى حصاة اللبن ..~
 
الرئيسيةأحدث الصورالتسجيلدخول
منتدى حصاة اللبن يرحب بكمSmile Smile

 

 كيف تتعلم الرسم بالحاسوب بلغة السيc ....؟

اذهب الى الأسفل 
كاتب الموضوعرسالة
المدير العام
Admin
المدير العام


عدد المساهمات : 246
تاريخ التسجيل : 03/07/2012

كيف تتعلم الرسم بالحاسوب بلغة السيc ....؟ Empty
مُساهمةموضوع: كيف تتعلم الرسم بالحاسوب بلغة السيc ....؟   كيف تتعلم الرسم بالحاسوب بلغة السيc ....؟ I_icon_minitimeالثلاثاء يوليو 03, 2012 9:43 pm

بسم الله الرحمـــن الــرحيم



مقدمة عن الرسم بالحاسوب بلغة السي 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: intgdriver = EGA* gmode = EGAHI; */
intgdriver = 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"
وبذلك نكون قد تعرفنا على بيئة الرسم كيفية تهيئتها وكيفية إغلاقها، تذكر هاتان الدالتان 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 (intxa* intya* intxb* intyb)
{
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()
{
intgraphdriver=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، فإن كان العدد صحيحاً منذ البداية لم يتأثر بإضافة النصف إليه، وإن كان كسرياً من البداية فإنه سيصبح صحيحاً بعد إضافة النصف إليه...

وهذه هي طرق رسم الخط المستقيم في الســـــــــي
أرجـــــو من الله أن يكون الدرس واضحاً
والسلام عليكم ورحمه الله..
الرجوع الى أعلى الصفحة اذهب الى الأسفل
https://hasah.yoo7.com
 
كيف تتعلم الرسم بالحاسوب بلغة السيc ....؟
الرجوع الى أعلى الصفحة 
صفحة 1 من اصل 1

صلاحيات هذا المنتدى:لاتستطيع الرد على المواضيع في هذا المنتدى
حصاة اللبن :: عالم الكمبيوتر ..~-
انتقل الى: