استفاده از initwindow، putpixel، line، circle، setcolor
پیادهسازی رسم دایره از روی دو نقطه قطر با محاسبات ریاضی
آگاهی از محدودیتهای graphics.h و آشنایی با جایگزینهای مدرن
مقدمهای بر گرافیک در C++
تاکنون تمام خروجی برنامههایمان متنی (Console) بود. اما C++ میتواند با کمک کتابخانههای گرافیکی خروجی بصری نیز تولید کند: نقاشی، نقاط، خطوط، دایره و...
معمولترین کتابخانهای که در دانشگاههای ایران تدریس میشود، graphics.h است که در اصل بخشی از کتابخانه BGI (Borland Graphics Interface) متعلق به کامپایلرهای قدیمی Borland Turbo C++ بود. امروزه نسخهی WinBGIm آن روی ویندوز با Dev-C++ و برخی نسخههای MinGW اجرا میشود.
ساختار کلی یک برنامه گرافیکی:
main.cppcpp
هشدار: graphics.h کتابخانهای قدیمی و غیراستاندارد است
کتابخانه graphics.hبخشی از استاندارد C++ نیست. این کتابخانه در دهه ۱۹۹۰ توسط شرکت Borland برای محیط DOS معرفی شد و امروزه فقط با نصب دستی WinBGIm روی برخی کامپایلرهای خاص کار میکند.
مشکلات:
روی کامپایلرهای مدرن GCC، Clang، MSVC بهصورت پیشفرض در دسترس نیست.
فقط روی ویندوز بهخوبی کار میکند.
API آن قدیمی و محدود است.
استفاده آموزشی: با این حال چون سینتکس سادهای دارد و در بسیاری از دانشگاهها و کنکورهای کارشناسی ارشد ایران هنوز پرسش میشود، آشنایی با آن مفید است. اما برای پروژههای واقعی از کتابخانههای مدرن استفاده کنید که در انتهای این درس معرفی شدهاند.
اولین برنامه گرافیکی
ایجاد پنجره و رسم یک پیکسل سفیدcpp
توابع initwindow و closegraph
دو تابع کلیدی برای شروع و پایان برنامه گرافیکی:
initwindow(width, height): یک پنجره با ابعاد دادهشده ایجاد میکند و حالت گرافیکی را فعال میسازد.
closegraph(): حالت گرافیکی را خاتمه داده و پنجره را میبندد.
در برخی نسخههای قدیمی، بهجای initwindow از initgraph با پارامترهای پیچیدهتر استفاده میشد که امروزه منسوخ شده است.
برای جلوگیری از بستهشدن فوری پنجره، قبل از closegraph معمولاً getch() میگذاریم تا برنامه منتظر فشردن یک کلید بماند («معطل میشه» به قول جزوه).
سیستم مختصات گرافیکی
در گرافیک C++، مبدأ مختصات (۰، ۰) در گوشه بالا-چپ پنجره قرار دارد، نه در مرکز یا پایین-چپ.
محور X به سمت راست افزایش مییابد.
محور Y به سمت پایین افزایش مییابد، برعکس ریاضیات!
واحد مختصات پیکسل (Pixel) است. در یک پنجره ۸۰۰×۶۰۰:
گوشه بالا-چپ: (0, 0)
گوشه بالا-راست: (799, 0)
گوشه پایین-چپ: (0, 599)
گوشه پایین-راست: (799, 599)
چون Y رو به پایین است، در محاسبات هندسی باید علامت مناسب را در نظر بگیرید (مثلاً برای رسم اشکال بهصورت ریاضی، باید Y را معکوس کنید).
فلوچارت ساختار برنامه گرافیکی
flow.svg
رنگها در BGI
در BGI رنگها معمولاً به دو شکل مشخص میشوند:
۱) ثابتهای از پیش تعریفشده (۱۶ رنگ):
عدد
نام
رنگ
0
BLACK
سیاه
1
BLUE
آبی
2
GREEN
سبز
3
CYAN
فیروزهای
4
RED
قرمز
5
MAGENTA
سرخابی
6
BROWN
قهوهای
7
LIGHTGRAY
خاکستری روشن
8
DARKGRAY
خاکستری تیره
9
LIGHTBLUE
آبی روشن
10
LIGHTGREEN
سبز روشن
11
LIGHTCYAN
فیروزهای روشن
12
LIGHTRED
قرمز روشن
13
LIGHTMAGENTA
سرخابی روشن
14
YELLOW
زرد
15
WHITE
سفید
۲) ماکرو COLOR(R, G, B):
در WinBGIm میتوان با COLOR(r, g, b) رنگ دلخواه ساخت که هر مؤلفه ۰ تا ۲۵۵ است.
main.cppcpp
تابع setcolor(c) رنگ فعلی را برای رسم بعدی تنظیم میکند.
نمایش طیف رنگی
رسم ۲۵۶ خط عمودی با رنگهای متفاوتcpp
توابع رسم پایه: line، circle، rectangle
سه تابع پرکاربرد برای رسم اشکال:
line(x1, y1, x2, y2): خط از (x1,y1) به (x2,y2).
circle(x, y, r): دایره با مرکز (x,y) و شعاع r.
rectangle(x1, y1, x2, y2): مستطیل با گوشههای مخالف (x1,y1) و (x2,y2).
putpixel(x, y, c): نقطه با رنگ c در (x,y).
bar(x1, y1, x2, y2): مستطیل توپر.
fillellipse(x, y, rx, ry): بیضی توپر با شعاعهای افقی rx و عمودی ry.
توجه: آرگومانهای این توابع در نسخه اصلی BGI از نوع int هستند. اگر با متغیرهای double کار میکنید، قبل از ارسال به تابع، آنها را به int تبدیل کنید.
مثال: رسم دایره از روی قطر دو نقطه
فرض کنید دو نقطه (x1, y1) و (x2, y2) را داریم که قطر یک دایره را مشخص میکنند. میخواهیم خطی بین آن دو رسم کنیم و سپس دایرهای که این خط قطر آن است.
محاسبات:
مرکز دایره = میانگین دو نقطه: xC = (x1+x2)/2, yC = (y1+y2)/2
قطر = فاصله اقلیدسی دو نقطه: d = √((x1-x2)² + (y1-y2)²)
شعاع = d/2
رسم: circle(xC, yC, d/2)
برای محاسبه جذر از تابع sqrt در هدر <cmath> (یا <math.h>) استفاده میشود.
main.cppcpp
فلوچارت رسم دایره از روی قطر
flow.svg
تبدیل double به int برای توابع گرافیکی
توابع گرافیکی BGI آرگومانهای int میگیرند. اگر با double کار میکنید، قبل از ارسال به تابع، آن را cast کنید:
main.cppcpp
بدون این cast ممکن است کامپایلر هشدار بدهد یا در برخی نسخهها مقدار بهصورت بریدهشده رفتار عجیب کند.
هدر <cmath> بهجای <math.h>
در C++ مدرن بهجای #include <math.h> از #include <cmath> استفاده کنید. این هدر توابع ریاضی sqrt, sin, cos, pow, fabs و ... را در فضای نام std فراهم میکند.
جایگزینهای مدرن برای graphics.h
برای پروژههای واقعی بهجای graphics.h از کتابخانههای مدرنتر استفاده کنید:
برنامهای بنویسید که پنجرهای ۶۰۰×۴۰۰ ایجاد کند، یک خط از گوشه بالا-چپ به پایین-راست، یک دایره با مرکز (۳۰۰، ۲۰۰) و شعاع ۵۰ به رنگ قرمز، و یک مستطیل اطراف دایره به رنگ آبی رسم کند.
نمایش راهنما
از `line`, `setcolor(RED)`, `circle`, `setcolor(BLUE)`, `rectangle` استفاده کنید. مستطیل باید از (250,150) تا (350,250) باشد.
02
تمرین•حل کامل دارد
برنامهای بنویسید که ۲۰ دایره هممرکز با مرکز (۴۰۰، ۳۰۰) و شعاعهای ۱۰، ۲۰، ۳۰، ... تا ۲۰۰ رسم کند. رنگها را به ترتیب از ۱ تا ۱۵ تغییر دهید (با باقیمانده تقسیم بر ۱۵).
نمایش راهنما
حلقه for از i=1 تا 20، شعاع i*10، رنگ (i % 15) + 1.
03
تمرین•حل کامل دارد
برنامهای بنویسید که سه نقطه از ورودی بگیرد و مثلثی با رأسهای آن سه نقطه رسم کند. سپس مرکز ثقل مثلث (میانگین مختصات) را با یک نقطه قرمز نشان دهد.
نمایش راهنما
مرکز ثقل = میانگین سه مختصات. از putpixel یا circle با شعاع ۳ برای نشان دادن نقطه استفاده کنید.
04
تمرین•حل کامل دارد
برنامهای بنویسید که طیف رنگی رنگینکمان را رسم کند: ۷ مستطیل افقی پشت سر هم با رنگهای قرمز، نارنجی، زرد، سبز، آبی، نیلی، بنفش (از COLOR استفاده کنید).
نمایش راهنما
از `bar(x1, y1, x2, y2)` برای هر نوار و از `COLOR(r, g, b)` برای رنگ استفاده کنید. هفت نوار از y=0 تا y=350 هر کدام با ارتفاع ۵۰.
// نکات-کلیدی۶
01کتابخانه `graphics.h` بخشی از استاندارد C++ نیست و ریشه در BGI شرکت Borland دارد؛ امروزه بهصورت WinBGIm روی ویندوز قابل نصب است.
02مبدأ مختصات گرافیکی در گوشه بالا-چپ است و محور Y رو به پایین افزایش مییابد (برعکس ریاضیات).
03`initwindow(w, h)` پنجره را باز میکند و `closegraph()` آن را میبندد؛ برای نگهداشتن پنجره از `getch()` استفاده کنید.
04رنگها یا از طریق ثابتهای ۱۶تایی (مانند RED, BLUE) یا با `COLOR(R, G, B)` مشخص میشوند.
05برای رسم دایره از روی قطر دو نقطه، مرکز = میانگین نقاط و شعاع = نصف فاصله اقلیدسی است.
06برای پروژههای واقعی بهجای graphics.h از raylib، SFML، SDL2 یا Qt استفاده کنید.
گام بعدی پیشنهادی
رسم اشکال و چندضلعیها
دایره محاطی، تقسیم مثلث، چندضلعی منتظم، دایرههای تصادفی و هممرکز
1#include<graphics.h>2#include<conio.h>34intmain(){5initwindow(800,600);67// طیف خاکستری از مشکی تا سفید8for(int i =0; i <=255; i++){9setcolor(COLOR(i, i, i));10line(i *2,0, i *2,100);// هر ستون 2 پیکسل11}1213// طیف قرمز14for(int i =0; i <=255; i++){15setcolor(COLOR(i,0,0));16line(i *2,150, i *2,250);17}1819getch();20closegraph();21return0;22}23
1#include<iostream>2#include<cmath>3#include<graphics.h>4#include<conio.h>5usingnamespace std;67intmain(){8double x1, y1, x2, y2, xC, yC, d;910 cout <<"x1 y1 x2 y2: ";11 cin >> x1 >> y1 >> x2 >> y2;1213initwindow(800,600);1415// رسم قطر16line((int)x1,(int)y1,(int)x2,(int)y2);1718// محاسبه مرکز و قطر19 xC =(x1 + x2)/2.0;20 yC =(y1 + y2)/2.0;21 d =sqrt((x1 - x2)*(x1 - x2)+(y1 - y2)*(y1 - y2));2223// رسم دایره با شعاع d/224setcolor(YELLOW);25circle((int)xC,(int)yC,(int)(d /2));2627getch();28closegraph();29return0;30}31
flow.svg100%
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.