Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych. Autor artykułu: mgr Jerzy Wałaszek, wersja1.0 |
©2010 mgr
Jerzy Wałaszek |
Zanim przystąpisz do tej lekcji, zapoznaj się z poprzednimi lekcjami:
Wstęp do grafiki - biblioteki SDL i newgfx
Opis
biblioteki newgfx
Grafika - wielokąty
Na tych zajęciach pokażemy, iż stworzenie prostej aplikacji rysującej wykresy dowolnych funkcji matematycznych nie jest wcale rzeczą trudną.
Postępujemy wg następującej metody:
Określamy przedział argumentów, w którym będzie tworzony wykres. Dla prostoty oznaczmy ten przedział za pomocą xp i xk:
Przedział <xp,xk> dzielimy na n równoodległych punktów x0,x1,...,xn-1:
Odległość pomiędzy dwoma sąsiednimi punktami wynosi dx. Łatwo zauważysz, że n punktów dzieli przedział na n-1 części o długości dx, zatem:
Poszczególne punkty podziałowe wyznaczymy wg wzorów:
Dla każdego punktu xi wyznaczymy i zapamiętamy wartość funkcji w tym punkcie:
Otrzymane punkty (xi,yi) posłużą nam jako końce odcinków, z których będzie zbudowany wykres funkcji. W trakcie wyznaczania współrzędnych yi wyszukamy wśród nich wartości:
ymin - najmniejsza wartość yi
ymax - największa wartość yi.
Cały wykres funkcji mieści się teraz w prostokącie:
Lewy górny narożnik tego prostokąta ma współrzędne xp,ymax, prawy dolny narożnik ma współrzędne xk,ymin. Prostokąt ten należy odwzorować na ekranie graficznym w prostokąt ekranowy:
xep,yep - to współrzędne lewego górnego narożnika prostokąta. Pamiętaj, że na powierzchni graficznej początek układu współrzędnych rozpoczyna się w lewym górnym narożniku - wyprowadzone przez nas wzory przeliczeniowe będą to odzwierciedlać.
w - szerokość prostokąta w pikselach
h - wysokość prostokąta w pikselach.
x,y - współrzędne dowolnego punktu wewnątrz prostokąta
xe,ye - odpowiednik ekranowy współrzędnych x,y.
Zadanie nasze polega na znalezieniu wzorów na xe i ye w zależności od x i y.
Na pierwszy rzut oka zadanie wydaje się trudne, jednakże skorzystajmy z prostych proporcji:
Ponieważ prostokąt ekranowy odwzorowuje prostokąt wykresu funkcji, to w obu muszą być spełnione proporcje:
Z kolei możemy zapisać:
Wstawiamy to do proporcji i otrzymujemy:
Te wzory pozwalają nam wyznaczyć bezpośrednio xe oraz ye:
Teraz wystarczy wyliczone wcześniej punkty xi,yi przeliczyć na punkty ekranowe xe,ye, które następnie łączymy odcinkami i wykres będzie gotowy.
Pozostaje problem dorysowania osi współrzędnych. Oś OX wpada w prostokąt wykresu funkcji, jeśli ymax i ymin posiadają różne znaki. Jeśli tak, to rysujemy na prostokącie ekranowym linię poziomą o szerokości okna. Początek linii jest na współrzędnej xep. Współrzędną ye obliczymy wg wcześniejszego wzoru wstawiając y = 0.
Podobnie z osią OY - oś ta znajdzie się w prostokącie ekranowym, jeśli xp i xk mają różne znaki. W takim przypadku w prostokącie ekranowym rysujemy pionową linię o wysokości prostokąta ekranowego. Współrzędną xe początku tej linii znajdziemy wg wzoru, wstawiając x=0. Współrzędna pionowa to yep.
Uruchom Code::Blocks, utwórz nowy projekt SDL i wpisz poniższy kod:
// Rysowanie wykresów funkcji // (C)2011 Koło Informatyczne // I LO w Tarnowie //------------------------------- #include "newgfx.h" #include <cmath> // Tutaj umieszczamy przepis funkcji //---------------------------------- double f(double x) { return x*cos(x)*sin(x*x); } int main(int argc, char *argv[]) { if(!SDL_Init(SDL_INIT_VIDEO)) { atexit(SDL_Quit); SDL_Surface * screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE); // najpierw definiujemy wszystkie stałe const int n = 200; // liczba punktów wykresu funkcji const double xp = -2; // początek przedziału argumentów const double xk = 5; // koniec przedziału argumentów const Sint32 xep = 4; // współrzędne lewego górnego narożnika prostokąta const Sint32 yep = 4; // ekranowego const Uint32 w = screen->w-10; // szerokość prostokąta ekranowego const Uint32 h = screen->h-10; // wysokość prostokąta ekranowego // teraz zmienne double x[n],y[n],dx,ymax,ymin; Sint32 xe,ye,i; // wyliczamy odległość pomiędzy dwoma punktami podziałowymi dx = (xk - xp) / (n - 1); // wyliczamy współrzędne punktów wykresu funkcji oraz ymax i ymin for(i = 0; i < n; i++) { x[i] = xp + i * dx; y[i] = f(x[i]); if(!i) ymax = ymin = y[0]; else { if(y[i] > ymax) ymax = y[i]; if(y[i] < ymin) ymin = y[i]; } } if(SDL_MUSTLOCK(screen)) SDL_LockSurface(screen); // Ekran graficzny wypełniamy kolorem białym: SDL_Rect r; r.x = r.y = 0; r.w = screen->w; r.h = screen->h; SDL_FillRect(screen,&r,0xffffff); // rysujemy osie, jeśli wpadają w prostokąt ekranowy if(ymin * ymax <= 0) // oś OX { ye = yep + ymax * (h - 1) / (ymax - ymin); gfxHLine(screen,xep,ye,0x000000,w); } if(xp * xk <=0) // oś OY { xe = xep - xp * (w - 1) / (xk - xp); gfxVLine(screen,xe,yep,0x000000,h); } // rysujemy wykres funkcji for(i = 0; i < n; i++) { xe = xep + (x[i] - xp) * (w - 1) / (xk - xp); ye = yep + (ymax - y[i]) * (h - 1) / (ymax - ymin); if(!i) gfxMoveTo(xe,ye); else gfxWuLineTo(screen,xe,ye,0xff0000); } if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_UpdateRect(screen, 0, 0, 0, 0); // oczekujemy klawisza ESC int waiting = 0; do { SDL_Event event; while (SDL_PollEvent(&event)) if ((event.type == SDL_QUIT) || ((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_ESCAPE))) waiting = 1; } while(!waiting); } return 0; } |
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe