Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

obrazek

Autor artykułu: mgr Jerzy Wałaszek

©2020 mgr Jerzy Wałaszek
I LO w Tarnowie

obrazek

Interpolacja

Wykresy funkcji

SPIS TREŚCI
Podrozdziały

Tworzenie wykresu

Wyświetlenie wykresu funkcji polega na odwzorowaniu punktów płaszczyzny (lub przestrzeni), na której powstał wykres, w piksele okna graficznego. Wyprowadzimy tutaj podstawowe wzory. Wykresy będziemy tworzyć za pomocą funkcji udostępnianych przez bibliotekę BGI, którą opisaliśmy skrótowo w poprzednim rozdziale. Jeśli chcesz skorzystać z grafiki w naszym artykule, zainstaluj bibliotekę BGI w swoim środowisku programowania.

Metoda tworzenia wykresu funkcji dwuwymiarowej jest następująca:

Określenie obszaru graficznego okna, w którym ma powstać wykres.

Zrobimy to za pomocą współrzędnych dwóch punktów:

xs,ys lewy górny narożnik obszaru graficznego wykresu
xe,ye prawy dolny narożnik obszaru graficznego

Jeśli obszar ten ma obejmować całe okno graficzne, to współrzędne obszaru możemy w prosty sposób uzyskać za pomocą funkcji biblioteki BGI:

int xs,ys,xe,ye;
...
xs = ys = 0;
xe = getmaxx();
ye = getmaxy();
...

Jeśli obszar nie obejmuje całego okna graficznego, to należy zdefiniować obszar roboczy (ang. viewport), w którym będą wykonywane operacje graficzne. W bibliotece BGI mamy do tego celu specjalną funkcję:

void setviewport(int left, int top, int right, int bottom, int clip);

Funkcja tworzy w bieżącym oknie graficznym wydzielony obszar, w którym będą wykonywane wszystkie operacje graficzne. Po utworzeniu tego obszaru współrzędne pikseli będą się odnosiły do lewego górnego narożnika obszaru roboczego, a nie do lewego górnego narożnika okna.

left,right współrzędne lewego górnego narożnika obszaru roboczego
right,bottom współrzędne prawego dolnego narożnika obszaru graficznego
clip parametr określa obcinanie grafiki do obszaru roboczego. Jeśli jest różny od zera, to wszystkie piksele wychodzące poza granice obszaru roboczego nie będą rysowane w oknie graficznym

Gdy obszar roboczy zostanie zdefiniowany, operacje graficzne będą wykonywane w tym obszarze. Współrzędne (0,0) będą się odnosiły do lewego górnego narożnika obszaru. Funkcje getmaxx() i getmaxy() będą zwracały maksymalną wartość współrzędnych x  i y  w obszarze roboczym. Przydatna może być jeszcze jedna funkcja:

void clearviewport(void);

Funkcja czyści zawartość obszaru roboczego. Treść okna graficznego leżąca na zewnątrz tego obszaru nie jest naruszana. Po wyczyszczeniu bieżąca pozycja graficzna jest ustawiana na pozycji (0,0), czyli w lewym górnym narożniku obszaru graficznego.

Gdy mamy już zdefiniowane współrzędne obszaru wykresu w oknie graficznym (xs,ys xe,ye), musimy zdefiniować współrzędne obszaru wykresu na płaszczyźnie, na której ten wykres jest tworzony:

xgs,ygs lewy górny narożnik obszaru wykresu na płaszczyźnie
xge,yge prawy dolny narożnik obszaru wykresu na płaszczyźnie

Oczywiste jest, iż w przypadku ogólnym obszar wykresu na płaszczyźnie nie będzie identyczny z obszarem roboczym w oknie graficznym. Jeśli chcemy odwzorować punkt wykresu (x,y) w piksel (xd,yd) obszaru roboczego, to musimy znaleźć wzory przeliczające x na xd oraz y na yd.

Wykorzystamy proporcję matematyczną. Wybierzmy dowolny punkt (x.y) na płaszczyźnie wykresu:

Oznaczamy odległości współrzędnych punktu (x,y) od współrzędnych lewego górnego narożnika obszaru wykresu (xgs,ygs):

Lx odległość współrzędnej x od xgs
Ly odległość współrzędnej y od ygs

Przejdźmy teraz do obszaru roboczego w oknie graficznym. Załóżmy, że piksel o współrzędnych (xd,yd) jest obrazem punktu (x,y) w obszarze wykresu na płaszczyźnie:

Oznaczmy współrzędne tego punktu na obszarze roboczym. Współrzędne te są jednocześnie odległościami od lewego górnego narożnika obszaru w pionie i w poziomie:

Współrzędna xd w obszarze roboczym okna odwzorowuje współrzędną x obszaru na płaszczyźnie wykresu. Tak samo współrzędna yd odwzorowuje współrzędną y. Tworzymy proporcje:

Wg szerokość obszaru wykresu na płaszczyźnie
Hg wysokość obszaru wykresu na płaszczyźnie

W szerokość obszaru roboczego w oknie graficznym
H wysokość obszaru roboczego w oknie graficznym

Ponieważ interesują nas tutaj tylko odległości pomiędzy współrzędnymi, a nie konkretne wartości współrzędnych, możemy przyjąć, iż szerokość obszaru w pikselach jest równa maksymalnej wartości współrzędnej xd w obszarze plus 1. To samo dla wysokości:

Obszary muszą być proporcjonalne:

Zatem:

W, H, Wg i Hg są wartościami stałymi i wystarczy je policzyć jeden raz przed tworzeniem wykresu:

Gdy mamy już wzory przeliczeniowe ze współrzędnych wykresu na płaszczyźnie na współrzędne w obszarze roboczym okna graficznego, możemy przystąpić do tworzenia wykresu w obszarze roboczym.

Osie układu współrzędnych

Zaczynamy od narysowania osi układu współrzędnych. Osie te będą odcinkami rysowanymi na całej szerokości i całej wysokości obszaru roboczego.

Obliczamy współrzędną yd osi OX:

Obliczamy współrzędną xd osi OY:

Jeśli wyznaczone współrzędne mieszczą się w obszarze roboczym, to rysujemy odpowiednie odcinki: poziomy dla osi OX na wysokości yd; pionowy dla osi OY na współrzędnej xd. Odcinek poziomy ma szerokość obszaru roboczego. Odcinek pionowy ma wysokość obszaru roboczego.

Wykres

Wykres funkcji stworzymy z łamanej zbudowanej z odcinków. Aby wyznaczyć współrzędne wierzchołków łamanej, postępujemy następująco:

Wykres będzie tworzony dla argumentów funkcji w przedziale od xgs do xge:

Przedział [xgs,xge] dzielimy na n równoodległych punktów:

Dla n punktów przedział [xgs,xge] dzielony jest na n - 1 równych segmentów. Stąd odległość między dwoma sąsiednimi punktami jest stała i wynosi:

Wartości punktów x0, x1, ..., xn wyliczymy z prostego wzoru:

Gdy mamy punkty xi, to obliczamy dla nich wartości funkcji:

Wyliczone punkty (xi,yi) definiują wierzchołki łamanej:

Łamana przybliża linię wykresu funkcji. Przybliżenie jest tym lepsze im więcej punktów łamanej.

Gdy mamy policzone współrzędne wierzchołków łamanej na obszarze wykresu, musimy je przeliczyć na współrzędne w obszarze roboczym okna graficznego. Tutaj wykorzystujemy poprzednio wyprowadzone wzory:

Wartości współrzędnych zaokrąglamy do liczb całkowitych (współrzędne pikseli w oknie graficznym są liczbami całkowitymi) i umieszczamy w tablicy. Następnie tablicę wykorzystujemy do narysowania łamanej za pomocą funkcji drawpoly().

Na początek:  podrozdziału   strony 

Opis osi

Wiemy już, jak narysować wykres funkcji, mając jej wartości. Pozostaje problem umieszczenia jednostek na osiach układu współrzędnych, aby wykres stał się bardziej czytelny. Wbrew pozorom nie jest to wcale takie proste i do rozwiązania tego problemu opracowano różne algorytmy. My wybierzemy najprostszy algorytm.

Załóżmy, iż mamy wartości ( argumentów lub samej funkcji ) mieszczące się w przedziale [ vmin,vmax ]. Umieśćmy ten przedział na osi liczbowej:

Przedział ten chcemy opisać n działkami, przy czym skrajne działki mogą wybiegać poza przedział:

Algorytm wyznaczania opisu osi

Dane wejściowe:

n liczba jednostek na osi, n  ∈ N.
vmin minimalna wartość w przedziale, vmin  ∈ R.
vmax maksymalna wartość w przedziale, vmax  ∈ R.

Dane wyjściowe

vlow wartość pierwszej działki na osi, vlow  ∈ R.
vhigh wartość ostatniej działki na osi, vhigh  ∈ R.
dv odległość pomiędzy sąsiednimi działkami, dv  ∈ R.

Zmienne pomocnicze

len długość przedziału, lenR.
ldv,pdv,mdv zmienne do wyliczania odstępu dv, ldv,pdv,mdv  ∈ R.

Lista kroków

K01: Jeśli vmin = vmax,
to vminvmin - 1
i   vmaxvmax +1
Jeśli przedział ma zerową długość, to modyfikujemy początek i koniec
K02: lenvmax - vmin Obliczamy długość przedziału
K03: Jeśli n < 2,
to n ← 2
Ustalamy liczbę działek
K04: Jeśli n > 2,
to nn - 2
 
K05: Obliczamy wstępną odległość pomiędzy działkami
K06: Modyfikujemy odległość dv do "ładnej wartości"
K07:  
K08:  
K09: Jeśli mdv > 5,
to mdv ← 10
inaczej jeśli mdv > 2,
to mdv ← 5
inaczej jeśli mdv > 1,
to mdv ← 1
Modyfikujemy współczynnik mdv do wartości 1, 2 lub 5
K10: Mamy zmodyfikowaną odległość
K11: Obliczamy pierwszą działkę
K12: Obliczamy ostatnią działkę
K13: Zakończ  

Poniższy program demonstruje działanie algorytmu opisu osi. Na wejściu program pobiera 3 liczby, n, vmin i vmax, czyli liczbę działek, początek i koniec przedziału.  Na wyjściu otrzymujemy pozycję pierwsze i ostatniej działki, a następnie program wypisuje wartości kolejnych działek, które obejmują przedział [ vmin,vmax ]. Liczba działek wynikowych może się różnić od n, ponieważ program stara się dobrać "ładny" odstęp pomiędzy działkami.

Dane wejściowe:

15 -1 2.2
Przykładowy program w języku C++
// Generacja opisu osi
// (C)2020 mgr Jerzy Wałaszek
// Metody numeryczne
//-------------------------------------

#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

// Program główny
//---------------

// Przyblizenie zera
double const EPS = 0.0000000001;

int main()
{
    setlocale(LC_ALL,"");
    cout << fixed << setprecision(4);

    unsigned int n;    // Liczba działek na osi
    double vmin,vmax;  // Punkty krańcowe przedziału wartości
    double vlow,vhigh; // Wartosci pierwszej i ostatniej działki
    double dv;         // Odstęp pomiędzy działkami
    double ldv,pdv,mdv,len;

    // Odczytujemy liczbę działek
    cin >> n;

    // Odczytujemy krańce przedziału
    cin >> vmin >> vmax;

    // Jeśli przedział ma zerową długość, to modyfikujemy jego końce
    if(fabs(vmin - vmax) < EPS)
    {
        vmin -= 1;
        vmax += 1;
    }

    // Obliczamy długość przedziału
    len = vmax - vmin;

    // Modyfikujemy liczbę działek
    if(n < 2) n = 2;
    //if(n > 2) n -= 2;

    // Obliczamy wstępną odległość pomiędzy działkami
    dv = len / ( n - 1 );

    // Modyfikujemy dv do "ładnej wartości"
    ldv = floor(log10(dv));
    pdv = pow(10,ldv);
    mdv = (int)(dv/pdv + 0.5);

    // Modyfikujemy współczynnik mdv do wartości 1, 2 lub 5
    if(mdv > 5.0)      mdv = 10.0;
    else if(mdv > 2.0) mdv = 5.0;
    else if(mdv > 1.0) mdv = 2.0;
    else               mdv = 1.0;

    // Obliczamy ostateczną odległość pomiędzy działkami
    dv = mdv * pdv;

    // Obliczmy pozycję pierwszej działki
    vlow = dv * floor(vmin / dv);

    // Obliczamy pozycję ostatniej działki
    vhigh = dv * ceil(vmax / dv);

    // Wyświetlamy wyniki
    double v;
    int i;

    cout << vlow << ", " << vhigh << endl << endl;

    i = 0;
    do
    {

        v = vlow + i * dv;
        cout << "v[" << setw(2) << i << "] = " << setw(9) << v << endl;
        i++;
    }
    while(v < vhigh);

    return 0;
}
Wynik
15 -1 2.2
-1.0000, 2.2000

v[ 0] =   -1.0000
v[ 1] =   -0.8000
v[ 2] =   -0.6000
v[ 3] =   -0.4000
v[ 4] =   -0.2000
v[ 5] =    0.0000
v[ 6] =    0.2000
v[ 7] =    0.4000
v[ 8] =    0.6000
v[ 9] =    0.8000
v[10] =    1.0000
v[11] =    1.2000
v[12] =    1.4000
v[13] =    1.6000
v[14] =    1.8000
v[15] =    2.0000
v[16] =    2.2000
Na początek:  podrozdziału   strony 

Wykres funkcji 2D

Poniższy program tworzy wykres funkcji dwuwymiarowej w oknie graficznym przy wykorzystaniu biblioteki BGI. Program został tak zaprojektowany, aby można go było wykorzystać w innych programach. Wykres tworzony jest przez funkcję graph2D( ), do której przekazujemy tablicę z kolejnymi współrzędnymi punktów (x,y). Liczba tych punktów przekazywana jest w parametrze n. Działanie programu zostało dokładnie opisane w komentarzach.

Na początek:  podrozdziału   strony 

P4

xxx

Na początek:  podrozdziału   strony 

P5

xxx

Na początek:  podrozdziału   strony 

P6

xxx

Na początek:  podrozdziału   strony 

P7

xxx

Na początek:  podrozdziału   strony 

P8

xxx

Na początek:  podrozdziału   strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2020 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.