Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Grafika i komunikacja człowieka z komputerem

Podobne prezentacje


Prezentacja na temat: "Grafika i komunikacja człowieka z komputerem"— Zapis prezentacji:

1 Grafika i komunikacja człowieka z komputerem
Algorytmy rastrowe

2 Wprowadzenie W urządzeniu rastrowym obraz (kartka, ekran monitora i inne) składa się ze skończonej liczby podstawowych elementów nazywanych pikselami. Elementy te uporządkowane tworzą siatkę prostokątną. Wielkość lxk określa rozdzielczość danego urządzenia graficznego, a odległość między środkami sąsiednich pikseli w poziomie do odległości w pionie określa wartość aspektu danego urządzenia. Np. dla karty CGA aspekt=22/25, a dla karty EGA=4/5. Każdy rysunek rysowany na urządzeniu rastrowym tworzy się przez wyświetlenie (zaznaczenie) skończonej liczby pikseli. Problemem staje się wtedy wybór dyskretnego zbioru pikseli odwzorowującego np. krzywą ciągłą na płaszczyźnie.

3 Rysowanie odcinka – algorytm Bresenhama - założenia
W większości zastosowań praktycznych dysponujemy współrzędnymi rzeczywistymi. Aby narysować odcinek we współrzędnych rastrowych musimy przejść do współrzędnych całkowitoliczbowych. Będzie rozważany zbiór pikseli ośmiospójny. Załóżmy, że x0<xk, 0<dy/dx/=1.

4 Rysowanie odcinka – algorytm Bresenhama - algorytm
Zaczynamy od piksela P(x0,y0). Ponieważ kąt nachylenia odcinka jest mniejszy od 45 stopni to następny piksel wybieramy pośród Si+1=(xi+1,yi) i Ti+1=(xi+1,yi+1). Wielkości s i t występujące na rysunku określone są wzorami: s=dy/dx(xi+1-x0)-yi-y0, t=(yi+1-y0)-dy/dx(xi+1-x0).

5 Rysowanie odcinka – algorytm Bresenhama - algorytm
Odejmując od siebie stronami oraz mnożąc przez dxi oznaczając ta wielkość przez di mamy: di=(s-t)dx=2dy(xi-x0)-2dx(yi-y0)+2dy-dx. Ponieważ dx>0, to znak di określa, która z wielkości s i t jest większa. Jeżeli di>0, to s>t i za Pi+1 przyjmiemy piksel Ti+1, w przeciwnym przypadku jeżeli di<0, to wybierzemy Si+1. Jeżeli di=0, to oba piksele leżą w tej samej odległości i możemy założyć, że wybieramy np. Pi+1=Ti+1.

6 Rysowanie odcinka – algorytm Bresenhama - algorytm
Dalej możemy zmniejszyć koszt obliczeń badając zachowanie wzoru na di dla i+1. Mamy: di+1=2dy(xi+1-x0)-2dx(yi+1-y0)+2dy-dx. Po odjęciu od siebie stronami mamy: di+1-di=2dy(xi+1-xi)-2dx(yi+1-yi). Stąd, ponieważ xi+1-xi=1, zachodzi: di+1=di+2dy-2dx(yi+1-yi).

7 Rysowanie odcinka – algorytm Bresenhama - algorytm
Jeżeli di>0 (wybieramy Pi+1=Ti+1) to zależność powyższa upraszcza się do postaci: di+1=di+2(dy-dx), a jeżeli di<0 to ponieważ yi+1=yi mamy: di+1=di+2dy. Aby zależności rekurencyjne działały określamy wartość di dla i=0: d0=2dy-dx.

8 Podsumowanie – algorytm końcowy (jedna z możliwych implementacji)
Zadanie: narysować odcinek łączący P0(x0,y0) z Pk(xk,yk) przy założeniu: dx=xk-x0>0, dy=yk-y0>0, 0<dy/dx<=1. Rysujemy P0=(round(x0), round(y0)), d0=2dy-dx d0<0=>Si+1, d0>0=> Ti+1, gdy d0=0, to losowy i=0, 1,…,k di+1= di + 2dy di+1<0=>Si+1, di+1>0=> Ti+1, gdy di+1=0, to losowy Wróć do pktu 4

9 Rysowanie odcinka – algorytm Bresenhama - podsumowanie
Ostatecznie widać, że algorytm ogranicza się do działania na liczbach całkowitych. Zgodnie z przyjętymi oznaczeniami i założeniami możemy oznaczyć wybór punktu Ti+1 jako T, a Si+1 jako S. Rysowanie odcinka możemy zapisać jako ciąg S i T, np. SSSTTTSSSTTT itd. lub (SSSTTT)^2 lub (S^3T^3)^2. Umożliwia to kompresję danych.

10 Rysowanie okręgu – algorytm Bresenhama
W przypadku rysowania okręgu wartość aspektu jest ważna. Dlatego przyjmujemy, że mając dany układ rzeczywisty OXY i pikselowy oxy związki między tymi układami są następujące: X=ax, Y=y. Uprościmy rysowanie okręgu do okręgu w środku układu i do promienia całkowitoliczbowego. Zadanie polega więc na przybliżeniu krzywej wybranym układem pikseli: X2+Y2=R2 lub we współrzędnych ekranowych (ax)2+y2=R2.

11 Rysowanie okręgu – algorytm von Akenema
Przyjmijmy, że a=p/q, a stąd mamy powyższą zależność możemy zapisać w postaci funkcyjnej: f(x,y)=p2x2+q2y2-q2R2=0. Stosujemy układ ośmiokierunkowy (ośmiopikselowy) i ze względu na symetrię ograniczymy się do pierwszej ćwiartki. Zaczynamy od piksela P0(0,R). Punkt, w którym współczynnik kierunkowy wektora stycznego: dy/dx=-fx/fy=-2p2x/(2q2y)=-1 dzieli ćwiartkę okręgu na dwa fragmenty. W pierwszym fragmencie, dla którego zachodzi p2x<q2y (rysunek powyżej) zwiększamy kolejno wartości x o jeden i wybieramy spośród pikseli oznaczonych jako A i B. W drugim fragmencie (rysunek obok) wybieramy między pikselami C i B. O wyborze będzie decydować wartość funkcji w punkcie S (algorytm Van Akenema). W pierwszym przypadku obliczamy: fsi=f(xi+1,yi-1/2).

12 Rysowanie okręgu – algorytm von Akenema
Jeżeli fsi=f(xi+1,yi-1/2)>0 to punkt S leży na zewnątrz okręgu i wtedy jako Pi+1 wybieramy punkt B. Jeżeli fsi=f(xi+1,yi-1/2)<0 to S leży wewnątrz okręgu i wybieramy wtedy punkt A. Dla drugiego przypadku obliczamy fsi=f(xi+1/2,yi-1) i wybieramy Pi+1=C, gdy fsi>0 i Pi+1=B gdy fsi<0.

13 Rysowanie okręgu – algorytm von Akenema
Jeżeli fsi=0, to wybieramy dowolny punkt. Dla startowego piksela P0(0,R) mamy: fs0=f(x0+1,y0-1/2)=p2(0+1)2+q2(R-1/2)2-q2R2=p2-q2R+q2/4 Dla pierwszego wariantu (p2x<q2y) mamy. Przy przejściu od Pi do Pi+1=A mamy xi+1=xi+1, yi+1=yi i stąd: f(xi+1+1,yi+1-1/2)=p2(xi+1+1)2+q2(yi+1-1/2)2-q2R2= p2(xi+1+1)2+q2(yi-1/2)2-q2R2 = =f(xi+1,yi-1/2)+2p2xi+1+p2 lub krócej na podstawie fsi=f(xi+1,yi-1/2) fsi+1=fsi+2p2xi+1+p2.

14 Rysowanie okręgu – algorytm von Akenema
W drugim przypadku (przy przejściu od Pi do Pi+1=B) mamy xi+1=xi+1, yi=yi-1 i zachodzi: f(xi+1+1,yi+1-1/2)=p2(xi+1+1)2+q2(yi-1/2-1)2-q2R2=f(xi+1,yi-1/2)+2p2xi+1+p2-2q2yi+1 lub krócej fsi+1=fsi+2p2xi+1+p2-2q2yi+1. Dla drugiego wariantu możemy przeprowadzić podobne rozważania otrzymamy wtedy: dla przejścia od Pi do Pi+1=B (xi+1=xi+1, yi+1=yi-1) mamy f(xi+1+1,yi+1-1/2)=p2(xi+1+1)2+q2(yi-1-1/2)2-q2R2=f(xi+1,yi-1/2)+2p2xi+1+p2-2q2yi+1 A po uproszczeniach dla przejścia od Pi do Pi+1=C (xi+1=xi, yi+1=yi-1) mamy fsi+1=fsi-2q2yi+1+q2.

15 Rysowanie okręgu – inne algorytmy
W przypadku, gdy chcemy wyznaczyć punkty okręgu niekoniecznie wszystkie piksele sąsiednie można skorzystać z innej metody. Polega ona na tym ,że okrąg możemy zapisać we współrzędnych biegunowych następująco: X=Rcos, Y=Rsin, Gdzie <0,360). Łatwo otrzymujemy: dX/d=-Rsin=-Y, dY/d=Rcos=X z warunkami początkowymi: X(0)=R, Y(0)=0. Taki układ możemy rozwiązać np. z krokiem h=360/(N+1)np. metodą Eulera lub niejawną metodą Eulera, np. X0=R, Y0=0 Xi+1=Xi-hYi, Yi+1=Yi+hXi+1. Dla i=0,1,...,N.

16 Wypełnianie obszaru

17 Wprowadzenie W wielu praktycznych zadaniach problemem jest wypełnienie obszaru zadanym kolorem lub wzorcem. Dzieje się tak w systemach interaktywnych, gdzie użytkownik myszą, piórem świetlnym lub przy pomocy tabliczki graficznej rysuje brzeg obszaru, wskazuje jego wnętrze i wybiera kolor lub wzorzec jakim on ma być wypełniony. W wielu innych zadaniach obszar może być dany w postaci wieloboku, a jego wierzchołkami są współrzędne rzeczywiste (nie ekranowe).

18 Wprowadzenie Rozróżnia się więc następujące sytuacje:
wypełniany obszar jest pewnym zbiorem pikseli o ustalonych własnościach (np. o danym kolorze) - jest to przypadek dyskretnym, wypełniany obszar dany jest w postaci wieloboku (jest on podany analitycznie przez krzywą zamkniętą składającą się odcinków i ew. łuków - jest to przypadek ciągły.

19 Przypadek dyskretny W tym przypadku wprowadza się następujące definicje: Zbiór pikseli jest spójny, gdy od dowolnego piksela z tego zbioru możemy przejść do każdego innego przez piksele sąsiednie. Rozważamy zbiór czterospójny, gdy za piksele sąsiednie są uważane piksele leżące odpowiednio: na górze, na dole, na lewo i na prawo od rozważanego piksela. Jeżeli dodatkowo rozważamy sąsiedztwo po kierunkach ukośnych to taki zbiór nazywamy ośmiospójnym. Ziarnem nazywać będziemy dowolny piksel leżący wewnątrz obszaru spójnego.

20 Przypadek dyskretny - definicje
Najczęściej rozważanym przypadkiem jest przypadek wnętrza czterospójnego i brzegu ośmiospójnego, rys. obok. Dopuszczamy także istnienie dziur (wysp) wewnątrz obszaru – będą to podobszary ograniczone ośmiospójnymi brzegami pikseli w zadanym kolorze.

21 Algorytm „przez sianie”
Najprostszy algorytm można skonstruować wykorzystując rekurencję, która polega na tym, że znając ziarno można „siać” kolor wnętrza (oznaczamy go jako Cn) we wszystkich czterech kierunkach (bo wnętrze jest czterospójne). Kolor brzegu oznaczamy jako Cb. Algorytm można zapisać następująco w postaci procedury (funkcja kolor(x,y) oznacza kolor badanego piksela, procedura setcolor(x,y,cn) ustawia kolor cn w zadanym pikselu):

22 Algorytm w postaci pseudokodu
procedure fill4(x,y,cb,cn) /* x,y -współrzędne piksla, */ /* cb,cn -kolor brzegu i wnętrza */ begin if color(x,y)<>cb and color(x,y)<>cn then begin setcolor(x,y,cn); fill4(x,y-1,cb,cn); fill4(x,y+1,cb,cn); fill4(x-1,y,cb,cn); fill4(x+1,y,cb,cn); end;

23 Przykład działania algorytmu
Przykład działania procedury dla prostokąta: prostokąt(0,0,10,10), ziarno (5,5). Fill4(5,5,cb,cn) Fill4(5,4,cb,cn) Fill4(5,3,cb,cn) Fill4(5,2,cb,cn) Fill4(5,1,cb,cn) Fill4(5,0,cb,cn) – powrót Fill4(5,1,cb,cn) – powrót Fill4(4,1,cb,cn) Fill4(4,0,cb,cn) ....

24 Uwagi Algorytm ten można praktycznie stosować jedynie dla niewielkich obszarów. W przypadku większych obszarów następuje szybko przepełnienie stosu. Algorytm jest także bardzo kosztowny, gdyż pojedynczy piksel bada się kilka razy.

25 Nowa idea Efektywniejsze metody otrzymujemy wtedy, gdy operujemy nie na pojedynczych pikselach ale na ich grupie. Najczęściej są to poziome segmenty definiowane jako ciągi leżące wewnątrz obszaru pikseli sąsiadujących ze sobą w poziomie, są one ograniczone z prawej i z lewej strony pikselami brzegowymi (przykładem są odcinki).

26 Nowa idea Schemat postępowania w takich przypadkach jest następujący:
wyznaczamy segment początkowy zawierający dane ziarno, wyznaczamy segmenty sąsiadujące z segmentem początkowym, mogą się one znajdować nad segmentem początkowym lub pod. W przypadku kilku segmentów leżących nad lub po układamy je na stosie np. wg. kolejności od lewej do prawej, postępowanie powtarzamy dla kolejnych elementów leżących na stosie.

27 Nowa idea – praktyczna realizacja
Typowym algorytmem dla rozważanej klasy jest algorytm Smitha, przykład na rys. na następnym slajdzie: mamy dane ziarno, segmentem jest linia, wypełniamy segment, wyznaczamy początkowe współrzędne pikseli sąsiednich (leżących najbardziej na lewo) nie wypełnionych jeszcze nowym kolorem; wyznaczone współrzędne segmentu i ewentualnie jego długość odkładamy na stos, piksel, którego adres leży na wierzchołku stosu bierzemy jako nowe ziarno, powtarzamy do momentu, aż stos będzie pusty, kolejnymi ziarnami są współrzędne ze stosu.

28 Przykład Przykład działania algorytmu Smitha pokazuje rysunek poniżej; x -jest ziarnem początkowym, piksele 1,2,...,6 są kolejnymi ziarnami.

29 Algorytmy wektorowe - przypadek ciągły
Dalej zajmiemy się przypadkiem ciągłym. W tym wariancie podstawowym elementem jest wielobok. Rozważmy szczególny przypadek wieloboku jakim jest trapez, rys. Wierzchołki na ogół nie są całkowite, a rzeczywiste, więc należy je zaokrąglić. Algorytm można zapisać następująco A=(x1,y1), B=(x2,y2), C=(x3,y3), D=(x4,y4): Niech ymin=round(y4); ymax=round(y1); cl=(x4-x1)/(y4-y1); cp=(x3-x2)/(y3-y2); dla y=ymin,ymin+1,..., ymax wyznacz punkt przecięcia linii poziomej y z x=x1+(y-y1)*cl i z x=x2+(y-y2)*cp; wypełnij nowym kolorem piksele leżące na tej linii od round(xl) do round(xp),

30 Dowolny wielokąt Zadanie wypełniania dowolnego wielokąta można sprowadzić do przypadku trapezu, lub do szczególnego przypadku trapezu jakim jest trójkąt. Algorytmem, który to wykorzystuje jest algorytm Brassela i Fegeasa, który jest stosowany do rozkładu wielokąta na sumę trapezów. Oprócz zagadnień związanych z wypełnianiem ten algorytm stosowany jest w rysowaniu obiektów oświetlonych trójwymiarowych lub gdy wielokrotnie wypełniamy obszary tego samego kształtu ale różnych rozmiarów (np. czcionki tego samego kroju). W algorytmie wykorzystywane jest pojęcie stalaktytu, stalagmitu i wierzchołka normalnego. Stalaktytem jest taki wierzchołek yk, dla którego zachodzi yk-1>yk, yk+1>yk. Natomiast regularnym jest ten wierzchołek, który nie jest ani stalaktytem ani stalagmitem. Zakładamy ponadto, że wielokąt jest zwykłym wielokątem, tzn. jego krawędzie nie przecinają się oraz przyjmujemy, że nie ma krawędzi poziomych.

31 Dowolny wielokąt Algorytm jest postaci (narzucającym się sposobem jest poprowadzenie linii przez wszystkie wierzchołki, otrzymuje się wtedy dużo trapezów): Dane: Wi=(xi,yi), i=1,...,n, uporządkowane odwrotnie do ruchu wskazówek zegara, (dla krawędzi WiWi+1 to co jest po lewej stronie należy do wielokąta.

32 Algorytm posortuj wierzchołki według rosnących wartości y, i=1,..,n, yi1<yi2,...<yin, dla i=i1, i2, ..., in niech lista LO zawiera odcinki (P1,P2), (P3,P4),..., (P2m-1,P2m), niech LK zawiera krawędzie (Wk1,Wk2), (Wk3,Wk4),... Wyznaczamy punkty przecięcia P1’, P2’,..., prostej y=yi z krawędziami LK, dołączamy trapezy (P1,P2;P1’,P2’), ..., (P2m-1,P2m;P2m-1’,P2m’) do wynikowych trapezów, Klasyfikujemy wierzchołek Wi i rozważamy: Wi jest regularny - jeśli yi-1<yi<yi+1 to wymieniamy w LK krawędź (Wi-1,Wi) na (Wi,Wi+1), a jeżeli zachodzą nierówności przeciwne to następuje wymiana odwrotna. Przyjmujemy nową LO={(p1’,P2’),(P3’,P4’),...,(P2m-1’,P2m)}, Wi jest stalaktytem (obydwa wierzchołki mają składowe większe niż yi, a dwu krawędzi, których jednym z końców jest Wi=(xi,yi) nie ma w LK). Modyfikujemy listę przecięcia P1’, P2’,..., P2m’, wstawiając do niej dwukrotnie wierzchołek Wi w takie miejsce, by były spełnione nierówności xj’<xi<xj+1’. Otrzymany ciąg P1’, P2’,...,Pj’Wi,Wi,Pj+1’,...,P2m’ oznaczamy jako P1”,P2”,...,P2m+2” i jako nową listę LO przyjmujemy (P1”,P2”), ..., (P2m+1”,P2m+2”). Wstawiamy krawędzie (Wi-1,Wi) i (Wi,Wi+1) do LK w miejsce określone kolejnością punktów przecięcia w nowej LO. Wi jest stalagmitem (Oba wierzchołki leżą poniżej Wi, a więc krawędzie (Wi-1,Wi) i (Wi,Wi+1) są już elementami listy LK i stąd wśród punktów P1’, P2’, ...., P2m’ przecięcia prostej y=yi z krawędziami LK występuje dwukrotnie wierzchołek Wi. Usuwamy te punkty, a pozostałe nazywamy P1”, P2”,..., P2m-2” i uaktualniamy LO jako {(P1”,P2”),..., (P2m-3”,P2m-2”)}. Z listy LK usuwamy krawędzie (Wi-1,Wi) i (Wi,Wi+1). next i LO i LK są roboczymi strukturami danych. LO zawiera odcinki linii poziomych leżące wewnątrz wielokąta, a LK zawiera krawędzie boczne trapezów.

33 Okienkowanie i obcinanie
W zastosowaniach elementy rysunku definiowane są w rzeczywistym układzie współrzędnych. Podczas przenoszenia na urządzenie graficzne następuje przejście od układu rzeczywistego do układu urządzenia graficznego. Można wtedy określać, jaki fragment rysunku ma być zobrazowany, oraz jak mają być usytuowane i jaka ma być ich wielkość. Wykonujemy wtedy dwie rodzaje operacji: okienkowanie, czyli odwzorowanie obszaru określonego we współrzędnych rzeczywistych na obszar zdefiniowany we współrzędnych danego urządzenia graficznego oraz obcinanie, czyli wyznaczenie elementów rysunku, leżących wewnątrz okna. Oknem nazywamy obszar w rzeczywistej przestrzeni, a widokiem nazywamy obszar obrazu na urządzeniu graficznym. Najczęściej oba prostokąty mają boki równoległe do osi układu. Okno określone jest wtedy liczbami Xmin, Xmax, Ymin, Ymax, a widok xmin, xmax, ymin, ymax.

34 Okienkowanie Transformacja operacji okienkowania jest postaci:
x=xmin+sx(X-Xmin), y=ymin+sy(Y-Ymin), gdzie odwzorowuje okno na cały widok. Składa się ona z następujących etapów: Xi’=Xi-minXi, Xi”=Xi/maxXi’, Xi”’= Xi”(xmax-xmin) Xi””=xmin+ Xi”’.

35 Okienkowanie bez deformacji
Na ogół sx<>sy i wtedy następuje deformacja rysunku. Możemy deformacji uniknąć wprowadzając zależności: dla sx<sy x=xmin+sx(X-Xmin), a dla sx>sy y=ymin+sy(Y-Ymin).

36 Obcinanie Natomiast w operacji obcinania będziemy zajmowali się wyznaczeniem elementów rysunku leżących w prostokątnym oknie. Wykorzystywane są wtedy algorytmy wyznaczania czy dany punkt leży wewnątrz dowolnego wielokąta oraz algorytmy obcinania odcinka. Przyjmujemy, że okno, do którego obcinamy punkty i odcinki, będzie zdefiniowany nierównościami: xmin<=x<=xmax oraz ymin<=y<=ymax.

37 Algorytm Cohena-Shuterlanda
Jeżeli współrzędne danego punktu P spełniają te nierówności, to leży on już wewnątrz okna. W przypadku odcinka zadanie jest trudniejsze. Zostaną podane dwie metody. Pierwsza to algorytm Cohena-Shuterlanda. W algorytmie Cohena-Shuterlanda każdemu końcu odcinka przypisujemy czterobitowy kod, bity są numerowane od prawego: kod(P)=b4 b3 b2 b1 i zachodzi: b1=1 gdy P leży na lewo od okna, b2=1 gdy P leży na prawo od okna, b3=1 gdy P leży poniżej okna, b4=1 gdy P leży powyżej okna, a w przeciwnym przypadku bity mają wartość zero.

38 Algorytm Cohena-Shuterlanda
Podane wyżej bity wyznacza się bardzo łatwo, gdyż b1 jest bitem znaku x-xmin, b2 jest bitem znaku x-xmax, b3 jest bitem znaku y-ymin, a b4 jest bitem znaku y-ymax. Jeżeli punkt leży wewnątrz okna to kod(P)=0000. Jeżeli odcinek leży wewnątrz okna, to kod(P1)=0000 i kod(P2)=0000. Jeżeli kod(P1) AND kod(P2)<>0, to np. gdy końce P1 i P2 leżą na lewo od okna to pierwsze bity (b1) są równe jeden. Jeżeli kod(P1) AND kod(P2)=0, to odcinek P1P2 może ale nie musi przecinać okno. Algorytm Cohena-Shuterlanda polega na tym, że koniec odcinka o kodzie niezerowym jest zastępowany punktem przecięcia badanego odcinka z prostą zawierającą jeden z boków odcinka, co powoduje odrzucenie fragmentu odcinka leżącego poza oknem. Następnie pozostała część odcinka jest obcinana prostymi zawartymi w pozostałych bokach.

39 Algorytm Cohena-Shuterlanda
Dane P1=(x1,y1), P2=(x2,y2), xmin, xmax, ymin, ymax, (*) oblicz kod(P1) i kod(P2); jeśli kod(P1)=kod(P2)=0000, to odcinek P1P2 leży wewnątrz okna a w przeciwnym razie jeśli kod(P1) AND kod(P2) <> 0000 to odrzuć cały odcinek początkowy; w przeciwnym razie jeśli kod(P1)=0000 to zamień za sobą punkty P1 i P2 oraz ich kody; jeśli b1=1 to y1=y1+(xmin-x1)*(y2-y1)/(x2-x1); x1=xmin w przeciwnym razie jeśli b2=1, to y1=y1+(xmax-x1)*(y2-y1)/(x2-x1); x1=xmax w przeciwnym razie, jeśli b3=1, to x1=x1+(ymin-y1)*(x2-x1)/(y2-y1); y1=ymin jeśli b4=1, to x1=x1+(ymax-y1)*(x2-x1)/(y2-y1); y1=ymax wróć do (*).


Pobierz ppt "Grafika i komunikacja człowieka z komputerem"

Podobne prezentacje


Reklamy Google