// (c) Dinko Korunic, 36355514, kreator@fly.srk.fer.hr // Zadatak broj 1 iz predmeta Racunalna grafika #include #include #include #include class MyDisplay { // klasa MyDisplay u kojoj se nalaze inicijalizacijske xlib // rutine, kao i postavljanje background i foreground boje, itd. XGCValues gcv; unsigned long wp, bp; int screen, winx, winy, winsx, winsy; public: Display *disp; Window win; GC gc; XEvent ev; MyDisplay(int _winx, int _winy, int _winsx, int _winsy); ~MyDisplay(); }; MyDisplay::MyDisplay(int _winx=0, int _winy=0, int _winsx=320, int _winsy=200) : winx(_winx), winy(_winy), winsx(_winsx), winsy(_winsy) { // konstruktor koji sluzi za misc. inicijalizaciju cout << "Initialising graphic subsystem.." << endl; // otvaranje displaya if ((disp=XOpenDisplay(NULL))==NULL) { cerr << "I can't open display." << endl; exit(EXIT_FAILURE); } screen=DefaultScreen(disp); // stvaranje prototipnog prozora win=XCreateSimpleWindow(disp, DefaultRootWindow(disp), winx, winy, winsx, winsy, 1, wp=WhitePixel(disp, screen), bp=BlackPixel(disp, screen)); XSelectInput(disp, win, StructureNotifyMask | KeyPressMask | ExposureMask); // mapiranje prozora XMapWindow(disp, win); while(1) { // cekaj dok nije gotovo XNextEvent(disp, &ev); if (ev.type==MapNotify) break; } gcv.foreground=wp; gcv.background=bp; // stvori gc gc=XCreateGC(disp, win, GCForeground | GCBackground, &gcv); cout << "done." << endl; } MyDisplay::~MyDisplay() { // destruktor za graficki engine cout << "Shutting graphic subsystem.." << endl; XFreeGC(disp, gc); XDestroyWindow(disp, win); XCloseDisplay(disp); cout << "done." << endl; } class MyDraw1 : public MyDisplay { // klasa MyDraw1 koja nasljedjuje osobine klase MyDisplay, dakle // ima dodatne svoje funkcije za crtanje linije itd, kao i // funkcije za graficki engine iz MyDisplay klase.. takodjer su // naslijedjeni i kostruktori i destruktori int x1, y1, x2, y2; void MyDrawLine(void); void MyWait(void); public: MyDraw1(int _x1, int _y1, int _x2, int _y2); }; MyDraw1::MyDraw1(int _x1, int _y1, int _x2, int _y2) : x1(_x1), y1(_y1), x2(_x2), y2(_y2) { // konstruktor.. MyDrawLine(); XDrawLine(disp, win, gc, x1, y1+20, x2, y2+20); XFlush(disp); MyWait(); } void MyDraw1::MyDrawLine(void) { // vlastita implementacija DrawLine rutine. // odredi udaljenost x-x i y-y int x0=abs(x2-x1),y0=abs(y2-y1),i; // ako su u istoj liniji, algoritam je trivijalan if (!x0) for(i=0;i<=y0;++i) XDrawPoint(disp, win, gc, x1, y1+i); else if (!y0) for(i=0;i<=x0;++i) XDrawPoint(disp, win, gc, x1+i, y1); else { // no, ako nije onda se stvar komplicira, te nam je // potrebno znati u kojem smjeru se trebamo gibati pri // crtanju... naprijed, nazad, gore, dolje.. int counter1=x1y0) { // udaljenost x-x je veca od y-y te cemo tu morati // raditi `interpolaciju' ratio=(float)y0/x0-.5; do { XDrawPoint(disp, win, gc, x, y); if (ratio>0.) y+=counter2, ratio-=1; x+=counter1; ratio+=(float)y0/x0; } while (x!=x2); } else { // obrnuto! ratio=(float)x0/y0-.5; do { XDrawPoint(disp, win, gc, x, y); if (ratio>0.) x+=counter1, ratio-=1; y+=counter2; ratio+=(float)x0/y0; } while(y!=y2); } } } void MyDraw1::MyWait(void) { // postavi wait na keypress XSelectInput(disp, win, KeyPressMask | ExposureMask); while(1) { XNextEvent(disp, &ev); if (ev.type==KeyPress) break; } } void MojUnosPodataka(int *x1, int *y1, int *x2, int *y2) { // unos podataka cout << "Unesi red x, y koordinate pocetne i krajnje tocke: "; cin >> *x1, cin >> *y1, cin >> *x2, cin >> *y2; } int main(void) { // unesi podatke, alociraj inicijaliziraj objekt i izadji.. int xx1,yy1,xx2,yy2; MojUnosPodataka(&xx1, &yy1, &xx2, &yy2); MyDraw1 MyDraw1Object(xx1, yy1, xx2, yy2); return EXIT_SUCCESS; }