Waldemar Izdebski Politechnika Warszawska Wydział Geodezji i Kartografii 1. Algorytmy związane z prezentacją danych Graficzna prezentacja danych przestrzennych jest odwzorowaniem informacji o obiektach, zgromadzonych w bazie danych na obraz w postaci mapy zrealizowany na ekranie monitora lub innego urządzenia wyjścia. Odwzorowanie niniejsze realizowane jest z wykorzystaniem odpowiedniego zestawu znaków umownych przyporządkowanych poszczególnym obiektom. Ponieważ proces prezentacji związany jest zawsze z przestrzenną lokalizacją prezentowanego obszaru terenu musi zatem być poprzedzony wyborem z bazy danych tych obiektów, które ze względów przestrzennych są do danej prezentacji przeznaczone. Trudno sobie bowiem wyobrazić, że będziemy rysowali wszystkie obiekty z bazy nawet jeśli znajdują się poza oknem prezentacji. Aby tego uniknąć najprościej zastosować wstępną selekcję obiektów, jak było to omawiane w rozdziale poświęconym dostępowi do danych przestrzennych, a następnie dokonywać odwzorowania (rysowania) tylko tych obiektów, które przeszły etap selekcji. W kolejnym etapie polegającym na rysowaniu obrazu wybranych obiektów będziemy dokonywali przeliczenia (transformacji) współrzędnych terenowych na współrzędne urządzenia i przy pomocy odpowiedniego znaku umownego prezentowali obiekty graficznie. Należy zwrócić uwagę na fakt, że praktycznie jedynym elementem geometrycznym wykorzystywanym do tworzenia rysunku będzie linia. To algorytm rysowania linii na urządzeniu będzie najbardziej wykorzystywany gdyż dzięki temu powstaje cały rysunek. W trakcie rysowania musimy jeszcze pamiętać o tym, że zakres urządzenia jest ograniczony i linie wykraczające z aktywnego obszaru urządzenia muszą zastać odpowiednio obcięte. Schematycznie funkcjonowanie takiego rozwiązania przedstawiono na rysunku 1.1. etap I wybór obiektów zawierających się w oknie prezentacji etap II prezentacja wybranych obiektów z obcinaniem do zakresu okna Rys. 1.1. Ilustracja wyboru obiektów do prezentacji graficznej
W pierwszym z przedstawionych etapów z całej bazy wybieramy te obiekty, które przynajmniej częściowo pokrywają się z oknem prezentacji a następnie w etapie drugim przedstawiamy graficznie wybrane obiekty przypisanymi im odpowiednimi znakami umownymi. Ponieważ nie wszystkie wybrane obiekty będą mieściły się w całości w oknie prezentacji dlatego w trakcie prezentacji należy już bardzo szczegółowo badać położenie poszczególnych linii stanowiących obrys obiektu lub jego znak umowny w stosunku do okna prezentacji i rysować tylko te fragmenty, które mieszczą się w oknie prezentacji. Przedstawiony powyżej sposób postępowania przy wyborze obiektów do prezentacji dotyczy przypadku, kiedy wyboru obiektów dokonywaliśmy z całej bazy danych. Sytuacja taka ma miejsce w chwili kiedy prezentację wykonujemy pierwszy raz. W chwili kiedy z zmniejszamy okno prezentacji wyboru możemy wykonywać jedynie z obiektów wybranych do prezentacji wcześniejszej. Schematycznie ilustruje to rysunek 1.2. Aby taką operację wykonać należy więc pamiętać, które obiekty były na ekranie przy poprzedniej prezentacji. Taka informacja zawsze towarzyszy prezentacji ze względu na możliwość wskazywania obiektów przy pomocy myszy. obiekty wybrane w poprzednim oknie prezentacji wybieranie obiektów do nowego (mniejszego) okna prezentacji Rys. 1.2. Pomniejszanie okna prezentacji prezentacja graficzna Przy powiększaniu okna niestety nie możemy już wykorzystać selekcji wstępnej wykonanej dla poprzedniego okna i musimy ponownie przeszukiwać całą bazę. Zagadnienia związane z wyborem danych na podstawie warunków przestrzennych były już poruszone w rozdziale związanym z organizacją dostępu do danych. Obecnie zajmiemy się drugim etapem w prezentacji graficznej jakim jest obcinanie rysowanych elementów na granicy okna prezentacji. Proces obcinania dotyczy zarówno rysowanych odcinków jak i elementów powierzchniowych jakimi są wielokąty. Należy w tym miejscu powiedzieć, że chodzi nie o brzeg wielokąta (gdyż to jest zwykłe rysowanie odcinków) lecz o reprezentację jego wnętrza. W procesie prezentacji graficznej dokonujemy odwzorowania fragmentu ciągłej przestrzeni rzeczywistej na fragment przestrzeń dyskretnej w postaci pikseli ekranu lub innego urządzenia. W procesie prezentacji następuje przeliczenie współrzędnych z jednego układu na drugi i ze względu na dyskretność układu ekranu, zaokrąglenie współrzędnych do wartości całkowitych. Obraz na urządzeniu uzyskujemy tylko wtedy kiedy uzyskane współrzędne mieszczą się w obszarze roboczym urządzenia (obszarze wyświetlania) w przeciwnym wypadku nie uzyskujemy żadnego obrazu lub obraz błędny. Brak obrazu spowodowany jest automatycznym obcinaniem dokonywanym przez urządzenie i jeśli obraz mieści się w dopuszczalnych wartościach współrzędnych urządzenia ale poza jego obszarem roboczym jest pomijany. Może się jednak zdarzyć, że wysłane w rezultacie do urządzenia współrzędne będą przekraczały dopuszczalne wartości urządzenia. Przeważnie urządzenie ignoruje wtedy bardziej znaczące bity co powoduje zawijanie się rysowanej konstrukcji wokół ekranu i powstawanie w rezultacie fałszywego obrazu jak przedstawiono to na rysunku 1.3.
X TEREN EKRAN X max x max x X min Ymin Ymax Y y max y Rys. 1.3. Przykład błędnej prezentacji odcinka Aby uniknąć przedstawionej wyżej sytuacji należy dokonywać obcięcia rysowanego odcinka w przestrzeni rzeczywistej a następnie dokonywać odwzorowania do przestrzeni dyskretnej. Postępowanie takie zagwarantuje poprawność wykonywanej prezentacji graficznej. W analogiczny sposób jak odcinków obcinanie dotyczy również wielokątów. TEREN EKRAN X X max x max x X min Y min Y max Y y max y Rys. 1.4. Obraz odcinka po obcięciu w przestrzeni rzeczywistej
Obcinanie odcinków Zagadnienie obcinania odcinków jest jednym z podstawowych zagadnień w procesie prezentacji danych w systemach informacji przestrzennej czy ogólnie mówiąc w zagadnieniach grafiki komputerowej. Procedury obcinania w trakcie prezentacji wykorzystywane są bardzo intensywnie i w dużej mierze od ich szybkości zależy czas wykonywania rysunku. O innych elementach mających wpływ na szybkość prezentacji będziemy mówili w dalszej części pracy. Istota obcinania polega na tym, że rysując obiekty na ekranie komputera czy kreśląc na ploterze będziemy chcieli uwzględnić tylko te fragmenty odcinków, które zawierają się w interesującym nas prostokątnym obszarze prezentacji. Możliwe położenia odcinków w stosunku do prostokąta obcinającego (okna prezentacji) przedstawiono na rysunku 1.5. D L E F A B C K H J G I Rys. 1.5. Różne przypadki położenia odcinków w stosunku do okna prezentacji Jeśli oba punkty końcowe odcinka leżą wewnątrz prostokąta obcinającego (na przykład AB), to cały odcinek leży wewnątrz prostokąta obcinającego i może być bezpośrednio zaakceptowany. Jeżeli jeden koniec odcinka leży wewnątrz prostokąta, a drugi na zewnątrz (na przykład CD), to odcinek przecina prostokąt i musimy wyznaczyć punkt przecięcia. Jeżeli oba końce odcinka leżą na zewnątrz prostokąta to odcinek może (ale nie musi) przecinać prostokąt (przypadki odcinków EF, GH, IJ) i musimy przeprowadzić dalsze obliczenia w celu ustalenia, czy są inne przecięcia, a jeżeli są, to gdzie się znajdują. Teoretycznie najprostszym rozwiązaniem jest wyznaczenie przecięć odcinka z każdą krawędzią prostokąta obcinającego i rysowanie tylko tej części, która mieści się w prostokącie. Ze względu jednak na wielokrotność wykonywania tego zadania bezpośrednie podejście do rozwiązania jest nieefektywne i należy szukać usprawnień, które spowodują znaczne przyspieszenie realizacji zadania. O tym jak istotny jest to problem świadczy fakt, że powstało wiele algorytmów usprawniających proces obcinania. Dwa z nich najbardziej znane opiszemy w dalszej części pracy oraz dokonamy ich porównania.
1.1.1 Algorytm Cohena-Sutherlanda Algorytmem znacznie przyspieszającym proces obcinania jest algorytm Cohena- Sutherlanda. Prawdopodobnie jest on najczęściej używany, ponieważ stosowany jest od dawna i był szeroko publikowany. Istotą algorytmu jest wykonanie testów początkowych dla odcinka, sprawdzających czy można go w całości zaakceptować lub odrzucić. Na przykład dwa proste porównania współrzędnych Y pokazują, że oba punkty końcowe odcinka EF (rysunek 1.6) mają współrzędne Y mniejsze od Y min i wobec tego leżą na lewo od prostokąta obcinającego. Oznacza to, że odcinek ten możemy bezpośrednio odrzucić. Podobnie możemy bezpośrednio odrzucić odcinki o obu końcach w obszarze na prawo od Y max na lewo od Y min poniżej X min i powyżej X max. Jeżeli odcinek nie może być bezpośrednio zaakceptowany ani odrzucony to należy go podzielić krawędzią obcinającą na takie części aby jedna z nich mogła być bezpośrednio odrzucona. Tak więc odcinek jest iteracyjne obcinany i sprawdza się czy może być już bezpośrednio odrzucony lub zaakceptowany. Algorytm jest szczególnie efektywny dla dwóch przypadków. W pierwszym gdy prostokąt obcinający jest duży i obejmuje całość lub większość elementów wyświetlanych, gdyż wtedy większość odcinków jest bezpośrednio akceptowana. W drugim przypadku, gdy prostokąt obcinający jest mały, gdyż prawie wszystkie odcinki można bezpośrednio odrzucić. W celu przedstawienia metody testowania w niniejszym algorytmie przedłużmy krawędzie prostokąta obcinającego tak aby podzieliły płaszczyznę na dziewięć obszarów (rysunek 1.6). N N' 11 F 1 D 11 D' L' L E L'' B H C K 1 H' A 1 N'' J M' G' G M I 11 1 11 Rys. 1.6. Idea metody Cohena-Sutherlanda obcinania odcinków Każdemu obszarowi przypisuje się 4-bitowy kod, wynikający z położenia obszaru w stosunku do prostokąta obcinającego. Każdy bit w kodzie przyjmuje wartość 1 (prawda) lub (fałsz). Cztery bity kodu spełniają następujące warunki: bit 1 półpłaszczyzna powyżej górnej krawędzi X>Xmax bit 2 półpłaszczyzna poniżej dolnej górnej krawędzi X<Xmin bit 3 półpłaszczyzna na prawo od prawej krawędzi Y>Ymax bit 4 półpłaszczyzna na lewo od lewej krawędzi Y<Ymin
Każdemu punkowi końcowemu odcinka przyporządkowany jest kod obszaru, do którego ten koniec należy. Posiadając kody punktów odcinka możemy stwierdzić czy odcinek leży całkowicie w prostokącie obcinającym albo w zewnętrznej półpłaszczyźnie krawędzi obcinającej. Jeżeli oba kody końców są zerowe wtedy odcinek leży całkowicie wewnątrz prostokąta. Jeżeli iloczyn logiczny kodów końców odcinka równy jest różny od zera to odcinek można bezpośrednio odrzucić co widzimy na przykładzie odcinka EF. Jeżeli odcinek nie może być bezpośrednio odrzucony lub zaakceptowany to jest dzielony na dwie części w taki sposób aby jedna z nich mogła być odrzucona. Podziału tego dokonujemy wykorzystując krawędź, która odcinek przecina. Część odcinka leżąca w zewnętrznej półpłaszczyźnie jest odrzucana. Możemy wybrać dowolny porządek testowania krawędzi ale zawsze musimy korzystać z tego samego porządku. W dalszej prezentacji niniejszego algorytmu będziemy korzystali z porządku krawędzi góra-dół-prawo-lewo. Istotną cechą wprowadzonego kodu jest to, że bity posiadające wartości różne od zera odpowiadają przecinanym krawędziom. Jeżeli jeden z punktów końcowych leży w półpłaszczyźnie zewnętrznej i odcinek nie spełnia kryterium bezpośredniego odrzucenia wtedy jego drugi punkt musi leżeć w wewnętrznej półpłaszczyźnie tej krawędzi i dlatego odcinek musi ją przecinać. Dlatego algorytm zawsze wybiera punkt, który leży na zewnątrz i potem wykorzystuje ustawiony bit kodu od określenia krawędzi obcinającej. Krawędź ta wybierana jest zgodnie z porządkiem góra-dół i prawolewo, to znaczy w kolejności określonej przez pierwszy z lewej strony bit w kodzie posiadający wartość zero. Działanie algorytmu wygląda więc następująco. Obliczamy kody dla obu końców i sprawdzamy czy odcinek można bezpośrednio odrzucić lub zaakceptować. Jeżeli żaden z testów nie daje wyniku pozytywnego znajdujemy ten koniec odcinka, który znajduje się na zewnątrz i na podstawie kodu znajdujemy przecinaną przez odcinek krawędź a następnie wyznaczamy punkt przecięcia. W punkcie przecięcia odcinamy odcinek od strony końca zewnętrznego zastępując koniec zewnętrzny punktem przecięcia i obliczamy kod nowego punktu końcowego w celu przygotowania się do następnej iteracji gdyż nie oznacza to jeszcze, że obliczony punkt przecięcia będzie należał do prostokąta. Widzimy to na rysunku 1.6 na przykładzie odcinka KL, gdzie w pierwszej iteracji zgodnie z przyjętym porządkiem przecinania krawędzi otrzymamy najpierw punkt L a dopiero w drugiej iteracji punkt L, który już będzie posiadał kod co przy kodzie punktu K również wynoszącym pozwoli zaakceptować odcinek KL. Jeszcze więcej bo aż 3 iteracje będzie wymagało wyznaczenie odcinka M N będącego fragmentem odcinka MN mieszczącym się w prostokącie obcinającym. Punkt M. posiada kod 1 jest więc punktem zewnętrznym. Sprawdzając kod stwierdzamy że pierwszą krawędzią obcinającą odcinek jest krawędź dolna. Wyznaczając punkt przecięcia znajdujemy punkt M posiadający już kod, czyli leżący wewnątrz prostokąta. przecina. Następna iteracja wybiera punktem zewnętrznym punkt N i na podstawie jego kodu wynoszącego 11 stwierdzamy, że punkt przecięcia leży na krawędzi górnej czyli sprowadzamy nasz punkt N do pozycji N. Kod wyznaczony w punkcie N wynosi 1. Na podstawie kodu stwierdzamy przecięcie z krawędzią lewą i po wyznaczeniu punktu przecięcia otrzymujemy do akceptacji odcinek M N. Jak widzimy mimo dużych usprawnień również w tym algorytmie występują zbędne obliczenia przecięć zewnętrznych na przykład punkty L, N. Możemy poprawić nieznacznie efektywność, jeżeli zapamiętamy nachylenie odcinków i nie będziemy go ponownie obliczali w następnej iteracji.
1.1.2 Algorytm parametryczny W roku 1978 Cyrus i Beck opublikowali ogólny algorytm obcinania odcinka 2D przez dowolny wielokąt wypukły na płaszczyźnie albo odcinka 3D przez dowolny wielościan wypukły w przestrzeni 3D. Istota algorytmu Cyrusa-Becka polega na wykorzystaniu w nim równania parametrycznego odcinka. Równanie to wyraża położenie dowolnego punktu odcinka w zależności od parametru t oraz punktów początkowego i końcowego odcinka. W zapisie wektorowym równanie parametryczne odcinka ma postać: P( t) P1 t( P2 P1 ) (1.1) gdzie P 1 - punkt początkowy odcinka P 2 - punkt końcowy odcinka t - parametr przybierający wartości t= dla punktu P1 i t=1 dla punktu P2. Do określania przecięcia linii Cyrus i Beck wykorzystali własność iloczynu skalarnego wektora normalnego do krawędzi obcinającej i wektora łączącego punkt na odcinku z dowolnym punktem leżącym na krawędzi. Rysunek 1.7 przedstawiono własności iloczynu skalarnego dla trzech możliwych położeń punktu na badanym odcinku. Przyjęto, że wektor normalny do krawędzi obcinającej skierowany jest na zewnątrz obszaru obcinającego. Krawędź obcinająca Na zewnatrz obszaru obcinającego E P2 P 1 N[P(t)-E]> N[P(t)-E]= N[P(t)-E]< N Wnętrze obszaru obcinającego Rys. 1.7. Ilustracja własności iloczynu skalarnego dla różnych położeń punktu Na podstawie przedstawionych własności możemy stwierdzić, w którym obszarze leży dowolny punkt odcinka P(t). Jeśli znak iloczynu skalarnego jest dodatni wtedy punkt znajduje się na zewnątrz a jeśli jest ujemny wtedy punkt znajduje się wewnątrz. półpłaszczyzny krawędzi obcinającej. Jeśli natomiast punkt znajduje się na krawędzi obcinającej wtedy wartość iloczynu skalarnego wynosi zero. N[ P( t) E] (1.2) Jest to własność która w niniejszym algorytmie wykorzystywana jest do obliczenia parametru t dla punktu przecięcia odcinka z krawędzią obcinającą. Przy czym jako punkt E przyjmujemy dowolny punkt na krawędzi obcinającej, najwygodniej punkt końcowy lub początkowy. W celu obliczenia parametru t dla punktu przecięcia podstawiamy do wyrażenia 1.2 równanie parametryczne odcinka 1.1 otrzymując: N[ P t( P P ) E] (1.3) 1 2 1 Po prostych przekształceniach otrzymujemy: Podstawiając N( P E) Nt ( P P ) (1.4) 1 2 1 D P 2 P 1 (1.5)
i rozwiązując względem t otrzymujemy ostatecznie: N ( P1 E) N ( E P1 ) t lub t ND ND Poprawną wartość wyrażenia otrzymujemy tylko wtedy kiedy mianownik wyrażenia jest różny od zera. Ponieważ N z definicji jest różne od zera, pozostają więc dwie możliwości sytuacjach, które należy badać w trakcie realizacji algorytmu. Jeśli D= co oznacza, że punkty P 1 i P 2 się pokrywają oraz jeśli ND= co oznacza, że odcinek jest równoległy do krawędzi i w związku z tym nie ma przecięcia z taką krawędzią. Otrzymane równanie wykorzystywane jest do znalezienia punktów przecięcia odcinka ze wszystkimi krawędziami obcinającymi. Obliczenia te wykonujemy określając normalną do krawędzi oraz dowolny punkt E leżący na krawędzi (np. na jej końcu). Po obliczeniu wszystkich parametrów t należy jeszcze określić, które z otrzymanych wartości parametrów odpowiadają wewnętrznym przecięciom odcinka z krawędziami obszaru obcinającego. Oczywiście może się zdarzyć, że żadne przecięcie nie będzie przecięciem wewnętrznym. Na początek tej analizy możemy odrzucić wszystkie wartości parametru spoza przedziału [,1], gdyż wtedy punkt przecięcia leży na zewnątrz odcinka. Dodatkowo jednak konieczna jest klasyfikacja przecięć jako potencjalnie wchodzących PE lub jako potencjalnie wychodzących PL (rysunek 1.8). PL B PL (1.6) C PE PE PE PL A C Rys. 1.8. Ilustracja obcinania odcinka wielokątem wypukłym metodą Cyrusa-Becka. Jeśli poruszając się od punktu P1 do punktu P2 przecinamy określoną krawędź tak że wchodzimy do wewnętrznej półpłaszczyzny krawędzi to takie przecięcie określamy jako PE natomiast jeśli wychodzimy z wewnętrznej półpłaszczyzny to jest to przecięcie typu PL. Przy takiej klasyfikacji dwa wewnętrzne punkty przecięcia będą posiadały przeciwne etykiety tzn. PE i PL. Formalnie klasyfikacji możemy dokonywać na podstawie wartości kata między P1 P2 oraz N. Jeżeli kąt jest mniejszy od 9, to przecięcie jest typu PL. Jeżeli wartość kąta jest większa od 9 to przecięcie jest typu PE. Nie będziemy jednak wykonywali obliczenia tych kątów lecz wykorzystamy fakt, że informacja o tym czy kąt jest większy czy mniejszy od 9 jest zawarta w znaku iloczynu skalarnego ND, który był wykorzystywany w mianowniku wyrażenia wykorzystywanego do obliczenia parametru t: ND PE (1.7) ND PL Tak więc obliczając parametry t dokonujemy ich klasyfikacji na punkty typu PE i PL a po wyznaczeniu wszystkich parametrów wybieramy odpowiednie parametry ograniczające obcięty odcinek. Aby dokonać wyboru odpowiednich parametrów musimy przeprowadzić pewna analizę. Część nieskończenie długiej linii przechodzącej przez punkty P 1 i P 2 leżąca wewnątrz obszaru obcinającego ograniczona jest przez punkt przecięcia PE o największej wartości parametru t określanego dalej jako t E oraz punkt przecięcia typu PL o najmniejszej
wartości parametru t określanego jako t L. Tak więc obcięty odcinek określony jest przez przedział parametru (t E t L ). Dodatkowo należy jeszcze zauważyć, że nie jesteśmy zainteresowani całą prostą a jedynie odcinkiem dla którego t [,1]. Wprowadzamy więc ograniczenie aby t= było dolną granicą dla t E oraz t=1 było górną granicą dla t L. W przypadku kiedy t E > t L cały odcinek leży poza obszarem obcinającym i należy go odrzucić przypadek odcinka CD. na rysunku 1.8. Kiedy mamy już ustalone odpowiednie parametry t E i t L możemy obliczyć współrzędne punktów określających obcięty odcinek. Widzimy więc, że metoda ta przeprowadza proces obcięcia operując parametrem t równania odcinka a dopiero na koniec oblicza współrzędne tylko tych punktów, które ograniczają obcięty odcinek. Unika się w ten sposób obliczania współrzędnych punktów przecięcia będących przecięciami zewnętrznymi, co jest przewagą nad metodą Cohena-Sutherlanda gdzie w niektórych sytuacjach musimy obliczać współrzędne zewnętrznych punktów przecięcia. Przedstawiony algorytm Cyrusa-Becka jest algorytmem ogólnym dotyczącym obcinania odcinka przez dowolny wielokąt wypukły i w takiej postaci został przedstawiony powyżej. Jednak jeśli przyjmiemy, że odcinek będziemy obcinali prostokątem o bokach równoległych do osi układu współrzędnych możemy dokonać w nim znacznych uproszczeń. Wykorzystując zalety prostokątnego obszaru obcinania w roku 1984 Liang i Barsky opublikowali swój algorytm obcinania odcinka parametrycznego, w którym dodatkowo wprowadzili efektywniejsze testy bezpośredniego odrzucania odcinka działające również dla ogólnych obszarów obcinania. Dzięki tym testom można niekiedy uniknąć obliczania parametrów t dla wszystkich krawędzi obcinających. Wykorzystując uproszczony do prostokąta obszar obcinania możemy wprowadzić uproszczenia wynikające ze znanej postaci wektorów normalnych poszczególnych krawędzi obcinających, które przedstawiono na rysunku 1.9. ND X P 1 P 2 N ( E P1 ) X max X P1 ND YP 1 P 2 N ( E P1 ) YP Ymin 1 ND YP 1 P 2 N ( E P1 ) Ymax Y P1 ND X P 1 P 2 N ( E P1 ) X P X min 1 Rys. 1.9. Uproszczenia wynikające z prostokątnego obszaru obcinania Ustalając kolejność krawędzi obcinających góra, prawo, dół, lewo i przyjmując następujące oznaczenia q N D i i pi Ni ( Ei P1 ) (1.8) wzór do obliczenia parametru t i dla przecięcia odcinka z i-tą krawędzią możemy zapisać w postaci qi ti p (1.9) i
3 4 B 1 2 A Rys. 1.1. Idea obcinania odcinka algorytmem Lianga-Barsky ego Zgodnie z przyjętymi oznaczeniami należy więc dla każdego z obcinanych odcinków obliczyć następujące wartości p X q X X p p p 1 2 3 4 Y P1 P2 P1 P2 X Y P1 P2 P1 P2 1 q Y Y 2 q X X 3 1 q Y Y 4 1 max max min P1 min P1 (1.1) a następnie parametry t odpowiadające przecięciu z poszczególnymi krawędziami okna co jest już dokładną realizacją opisanego wcześniej algorytmu Cyrusa-Becka. O tym czy ewentualny punkt przecięcia będzie sklasyfikowany jako potencjalnie wchodzący czy potencjalnie wychodzący będziemy wnioskowali ze znaku p i. 1.1.3 Porównanie algorytmów W celu porównania opisanych algorytmów w prostokątnym obszarze wygenerowano losowo dwa zestawy danych zawierających po 5. odcinków. W zestawie pierwszym długość odcinków limitowana była jedynie wielkością przyjętego obszaru a więc zawierał on odcinki od bardzo krótkich do bardzo długich. Schematycznie rozkład odcinków w pierwszym zestawie danych przedstawia rysunek 1.11. Rys. 1.11. Schemat rozmieszczenia odcinków w pierwszym zestawie danych Drugi zestaw danych został wygenerowany tak aby najdłuższe odcinki nie przekraczały wymiaru tysięcznej części dłuższego boku prostokąta. Ograniczenie długości odcinków wprowadzona w celu upodobnienia tego zestawu danych do sytuacji z jaką mamy do czynienia w systemach informacji przestrzennej. Schematycznie rozkład odcinków w drugim zestawie danych przedstawia rysunek 1.12. Rys. 1.12. Schemat rozmieszczenia odcinków w drugim zestawie danych Tak przygotowane zestawy danych poddawano obcinania w różnych oknach przy pomocy opisanych algorytmów. Aby nie zniekształcać wyniku testu pominięto rysowanie obciętych odcinków. Obliczenie wykonano na komputerze PC 586 166MHz przy pomocy procedur ClippCS, ClippCB, ClippLB, których kod w Borland Pascalu zamieszczono poniżej. Dla
pierwszego zestawu danych wyniki testu przedstawiamy w dwóch wariantach. W pierwszym wariancie podajemy zestawienie otrzymanych czasów obcinania w zależności od liczby odcinków, których przynajmniej część leży w oknie prezentacji w drugim natomiast w zależności od wielkości okna prezentacji. Ponieważ w drugim zestawie danych długość odcinków była ograniczona w związku z tym podajemy tylko jedno zestawienie czasów obcinania w zależności od wielkości okna gdyż zestawienie według odcinków pokrywa się z nim z dokładnością,1%. Przyjęte w tabelach i na wykresach skróty oznaczają odpowiednio: CS - algorytm Cohena-Sutherlanda CB- algorytm Cyrusa-Becka LB - algorytm Lianga-Barsky ego Poniżej zamieszczamy kody funkcji wykorzystywanych do testowania. Funkcje zwracają prawdę jeśli przynajmniej fragment odcinka x1, y1, x2, y2 mieści się w oknie prezentacji określonym przez xmin, ymin, xmax, ymax. Function ClippCS(var x1,y1,x2,y2:real;xmin,ymin,xmax,ymax:real):boolean; var k,k1,k2:byte;zl:boolean;x,y:real; function GetKod(x,y:real):byte; var k:byte; k:=;if (y<ymin) then k:=k or 1 else if (y>ymax) then k:=k or 2; if (x<xmin) then k:=k or 4 else if (x>xmax) then k:=k or 8; GetKod:=k; k1:=getkod(x1,y1);k2:=getkod(x2,y2);clippcs:=false; if (k1=) and (k2=) then ClippCS:=true;exit; if ((k1 and k2)<>) then exit; repeat if k1= then k:=k1;k1:=k2;k2:=k;x:=x1;x1:=x2;x2:=x;y:=y1;y1:=y2;y2:=y; if k1 and 1=1 then x1:=x1+(ymin-y1)*(x2-x1)/(y2-y1);y1:=ymin;end else if k1 and 2=2 then x1:=x1+(ymax-y1)*(x2-x1)/(y2-y1);y1:=ymax;end else if k1 and 4=4 then y1:=y1+(xmin-x1)*(y2-y1)/(x2-x1);x1:=xmin;end else if k1 and 8=8 then y1:=y1+(xmax-x1)*(y2-y1)/(x2-x1);x1:=xmax; k1:=getkod(x1,y1);if ((k1 and k2)<>) then exit;; until (k1=) and (k2=) ClippSC:=true; Function ClippCB(var x1,y1,x2,y2:real;xmin,ymin,xmax,ymax:real):boolean; var t,te,tl,dx,dy:real;p,q:array [1..4] of real;i:integer; te:=;tl:=1;dx:=x2-x2;dy:=y2-y1;clippcb:=false; p[1]:=dx;p[2]:=dy;p[3]:=-dx;p[4]:=-dy;{obliczamy parametry p i q} q[1]:=xmax-x1;q[1]:=ymax-y1;q[3]:=x1-xmin;q[4]:=y1-ymin; for i:=1 to 4 do if p[i]= then if q[i]< then exit else continue; t=q[i]/p[i];if p[i]< then if t>te then te:=t else else if t<tl then tl:=t; if (te>tl) then exit; x2:=x1+tl*dx;y2:=y1+tl*dy;x1:=x1+te*dx;y1:=y1+te*dy; ClippCB:=true; Function ClippLB(var x1,y1,x2,y2:real;xmin,ymin,xmax,ymax:real):boolean; var t,te,tl,dx,dy:real;p,q:array [1..4] of real;i:integer; te:=;tl:=1;clipplb:=false; p[1]:=dx;p[2]:=dy;p[3]:=-dx;p[4]:=-dy;{obliczamy parametry p i q} q[1]:=xmax-x1;q[1]:=ymax-y1;q[3]:=x1-xmin;q[4]:=y1-ymin; for i:=1 to 4 do if p[i]= then if q[i]< then exit else continue; t=q[i]/p[i]; if p[i]< then if t>tl then exit else if t>te then te:=t else else if t<te then exit else if t<tl then tl:=t; x2:=x1+tl*dx;y2:=y1+tl*dy;x1:=x1+te*dx;y1:=y1+te*dy;clipplb:=true;
Czas obcinania w [s] Czas obcinania w [s] Wyniki przeprowadzonych testów przedstawiono w tabelach 1.1, 1.2, 1.3 oraz na wykresach zamieszczonych na rysunkach 1.13, 1.14, 1.15. Tabela 1.1. Zestawienie czasów obcinania w zależności od liczby odcinków lezących w oknie Odcinki leżące Czas w sekundach w oknie (%) CB LB CS ZESTAW I 1, 4,83 5,5 2,25 95,935 5,5 5,22 3,18 83,673 5,17 5,1 3,68 61,1713 5,11 4,89 3,74 31,747 5,5 4,45 3,35 15,6533 4,95 4,17 3,8 12,464 4,89 4,12 2,96 9,2797 4,89 4,7 2,91 6,1533 4,89 4,1 2,81 3,267 4,89 3,95 2,75 1,533 4,89 3,9 2,64,763 4,83 3,84 2,64,37 4,83 3,84 2,63,15 4,83 3,84 2,63 a) 6, 5, 4, 3, 2, 1, CB LB CS, 1, 1, 1, Procent odcinków leżących w zakresie okna (skala logarytmiczna),1 b) 6, 5, 4, 3, 2, CB LB CS 1,, 1, 8, 6, 4, 2,, Procent odcinków leżących w zakresie okna Rys. 1.13. Wykresy czasu obcinania (I zestaw danych) w zależności od liczby odcinków w zakresie okna
Czas obcinania w [s] Czas obcinania w [s] Tabela 1.2. Zestawienie czasów obcinania w zależności od wielkości okna Wielkość Czas w sekundach okna w % CB LB CS ZESTAW I 1. 4.83 5.5 2.25 64. 5.5 5.22 3.18 36. 5.17 5.1 3.68 16. 5.11 4.89 3.74 4. 5.5 4.45 3.35 1. 4.95 4.17 3.8.64 4.89 4.12 2.96.36 4.89 4.7 2.91.16 4.89 4.1 2.81.4 4.89 3.95 2.75.1 4.89 3.9 2.64.25 4.83 3.84 2.64.4 4.83 3.84 2.63.1 4.83 3.84 2.63 a) 6. 5. 4. 3. 2. CB LB CS 1.. 1. 1. 1..1.1.1.1 Wielkość okna w % (skala logarytmiczna) b) 6. 5. 4. 3. 2. CB LB CS 1.. 1. 9. 8. 7. 6. 5. 4. 3. 2. 1.. Wielkość okna w % Rys. 1.14. Wykresy czasu obcinania (I zestaw danych) w zależności od wielkości okna
Czas obcinania w [s] Czas obcinania w [s] Tabela 1.3. Zestawienie czasów obcinania w zależności od wielkości okna (drugi zestaw danych) Wielkość Czas w sekundach okna w % CB LB CS ZESTAW II 1. 4.83 5.6 2.31 64. 4.83 4.61 2.31 36. 4.78 4.17 2.3 16. 4.78 3.85 2.25 4. 4.78 3.52 2.25 1. 4.78 3.46 2.25.64 4.78 3.41 2.2.36 4.78 3.4 2.2.16 4.78 3.35 2.2.4 4.78 3.35 2.2.1 4.78 3.35 2.2.25 4.78 3.35 2.2.4 4.78 3.35 2.2.1 4.78 3.35 2.2 a) 6. 5. 4. 3. 2. CB LB CS 1.. 1. 1. 1..1.1.1.1 Wielkość okna w % (skala logarytmiczna) b) 6. 5. 4. 3. 2. CB LB CS 1.. 1. 9. 8. 7. 6. 5. 4. 3. 2. 1.. Wielkość okna w % Rys. 1.15. Wykresy czasu obcinania (II zestaw danych) w zależności od wielkości okna
W wyniku przeprowadzonego testu najefektywniejszym okazał się algorytm Cohena-Sutherlanda zarówno w pierwszym jak i drugim zestawie danych. Jest on lepszy od pozostałych testowanych algorytmów bez względu na wielkość okna prezentacji czy liczbę odcinków podlegających obcinaniu. Dzięki wykonywaniu prostego testowania, przed obliczeniami, pozwalającego odcinek bezpośredni odrzucić lub zaakceptować, szczególna efektywność algorytmu ujawnia się w sytuacji kiedy większość odcinków jest akceptowana albo większość można bezpośrednio odrzucić. Pozostałe dwa algorytmy nie wykonujące testów początkowych przed obliczeniami są tu znacznie mniej efektywne. Przeprowadzone testy pozwalają zobaczyć, że modyfikacja wprowadzona przez Lianga i Barsky ego do algorytmu Cyrusa-Becka nie koniecznie poprawia jego efektywność. Z zamieszczonych zestawień wynika, że to dodatkowe odrzucanie Lianga-Barsky ego zaczyna mieć efekt pozytywny dopiero kiedy liczba odcinków, które mogą być bezpośrednio odrzucone przekracza 1% wszystkich odcinków w bazie. W przeciwnym wypadku czas obcinania tym algorytmem jest nieco dłuższy niż w algorytmie Cyrusa-Becka. 1.1.4 Propozycje usprawnień Przeprowadzone testy dotyczą algorytmów w takiej postaci w jakiej zostały zaproponowane przez ich autorów bez dodatkowych modyfikacji. Analizując je jednak szczegółowo oraz posiłkując się wynikami uzyskanych testów można znaleźć w nich elementy, które można zmodyfikować w celu poprawienia ich efektywności. Jako pierwszym zajmiemy się algorytmem Cohena-Sutherlanda, który w przeprowadzonych testach okazał się najlepszy. Poprawianiem efektywności algorytmu Cohena-Sutherlanda zajmowali się w pracy [Duvanenko 1996] Duvanenko, Robbins i Gyurcsik. Najistotniejsze modyfikacje dotyczyły wprowadzenie procedury obliczającej kody jednocześnie dla obu punktów końcowych z jednoczesnym sprawdzaniem czy odcinek może być w całości odrzucony oraz wyeliminowania procesu iteracyjnego obcinania odcinka na rzecz obcinania odcinka z dwóch stron jednocześnie. Poniżej przedstawiamy tekst procedury (w Borland Pascalu) zaproponowanej w pracy [Duvanenko 1996] do wyznaczania kodu i ewentualnie odrzucającej odcinki. W oryginale procedura przedstawiona była w języku C. function Skip(x1,y1,x2,y2:real;var k1,k2:byte):boolean; Skip:=true; if y1<ymin then if y2<ymin then exit else k1:=1 else if y1>ymax then if y2>ymax then exit else k1:=2 else k1:=; if x1<xmin then if x2<xmin then exit else if x2>xmax then k2:=8 else k2:=; k1:=k1 or 4; end else if x1>xmax then if x2>xmax then exit else if x2<xmin then k2:=4 else k2:=; k1:=k1 or 8; end else if x2<xmin then k2:=4 else if x2>xmax then k2:=8 else k2:=; if y2<ymin then k2:=k2 or 1 else if y2>ymax then k2:=k2 or 2; Skip:=false; {koniec funkcji Skip}
Tekst procedury realizującej tak zmodyfikowany algorytm obcinania z wykorzystaniem funkcji Skip przedstawiamy poniżej. Function ClippCSDRG(var x1,y1,x2,y2:real;xmin,ymin,xmax,ymax:real):boolean; var k1,k2:byte;dx,dy,edge:real; ClippSCDRG:=false;if Skip(x1,y1,x2,y2,k1,k2) then exit; if (k1=) and (k2=) then ClippCSDRG:=true;exit; dx:=x2-x1;dy:=y2-y1; if k1 and 3 <> then {jeśli jest przecięcie z lewą lub prawą krawędzią} if k1 and 1 =1 then edge:=ymin else edge:=ymax; x1:=x1+(edge-y1)*dx/dy;y1:=edge; if x1<xmin then if k2 and 4 =4 then exit else k1:=4 else if x1>xmax then if k2 and 8=8 then exit else k1:=8 else if k2= then ClippCSDRG:=true;exit;end else k1:=; if k1 and 12 <> then {jeśli jest przecięcie z górną lub dolną krawędzią} if k1 and 4 =4 then edge:=xmin else edge:=xmax; y1:=y1+(edge-x1)*dy/dx;x1:=edge; if (y1<ymin) or (y1>ymax) then exit; if k2= then ClippCSDRG:=true;exit; if k2 and 3 <> then if k2 and 1 =1 then edge:=ymin else edge:=ymax; x2:=x2+(edge-y2)*dx/dy;y2:=edge; if (x2<xmin) then k2:=4 else if x2>xmax then k2:=8 else ClippCSDRG:=true;exit; if k2 and 12 <> then if k2 and 4 =4 then edge:=xmin else edge:=xmax; y2:=y2+(edge-x2)*dy/dx;x2:=edge; ClippCSDRG:=true;exit; Przedstawiona procedura okazała się znacznie szybsza od procedury ClippCS ale po jej analizie zdecydowano się na wykonanie jeszcze pewnych dodatkowych modyfikacji, które przyspieszą jej realizację. Pierwszą modyfikacją jest rezygnacja z wywoływania procedury Skip i wstawienie obliczania kodu bezpośrednio do procedury obcinającej. Drugą jest wyeliminowanie zmiennej edge i podstawień z nią związanych. W wyniku tych modyfikacji ostateczna procedura przybiera postać przedstawioną poniżej. Function ClippCSDRGI(var x1,y1,x2,y2:real;xmin,ymin,xmax,ymax:real):boolean; var k1,k2:byte;x,y,dx,dy:real; ClippCSDRGI:=false;{wyznaczanie kodu i ewentualne odrzucenie odcinka} if y1<ymin then if y2<ymin then exit else k1:=1 else if y1>ymax then if y2>ymax then exit else k1:=2 else k1:=; if x1<xmin then if x2<xmin then exit else if x2>xmax then k2:=8 else k2:=; k1:=k1 or 4; end else if x1>xmax then
if x2>xmax then exit else if x2<xmin then k2:=4 else k2:=; k1:=k1 or 8; end else if x2<xmin then k2:=4 else if x2>xmax then k2:=8 else k2:=; if y2<ymin then k2:=k2 or 1 else if y2>ymax then k2:=k2 or 2; {koniec wyznaczania kodu punktów końcowych} if (k1=) and (k2=) then ClippCSDRGI:=true;exit; dx:=x2-x1;dy:=y2-y1; if k1 and 3 <> then {jeśli jest lewa lub prawa} if k1 and 1 =1 then x1:=x1+(ymin-y1)*dx/dy;y1:=ymin;end else x1:=x1+(ymax-y1)*dx/dy;y1:=ymax; if x1<xmin then if k2 and 4 =4 then exit else k1:=4 else if x1>xmax then if k2 and 8=8 then exit else k1:=8 else if k2= then ClippCSDRGI:=true;exit;end else k1:=; if k1 and 12 <> then {jeśli jest góra lub dół} if k1 and 4 =4 then y1:=y1+(xmin-x1)*dy/dx;x1:=xmin;end else y1:=y1+(xmax-x1)*dy/dx;x1:=xmax; if (y1<ymin) or (y1>ymax) then exit; if k2= then ClippCSDRGI:=true;exit; if k2 and 3 <> then if k2 and 1 =1 then x2:=x2+(ymin-y2)*dx/dy;y2:=ymin;end else x2:=x2+(ymax-y2)*dx/dy;y2:=ymax; if (x2<xmin) then k2:=4 else if x2>xmax then k2:=8 else ClippCS1:=true;exit; if k2 and 12 <> then if k2 and 4 =4 then y2:=y2+(xmin-x2)*dy/dx;x2:=xmin;end else y2:=y2+(xmax-x2)*dy/dx;x2:=xmax; ClippCSDRGI:=true;exit; W celu porównania procedur ClippCS, ClippCSDRG i ClippCSDRGI wykonano przy ich pomocy odcinanie odcinków z pierwszego zestawu danych otrzymując wyniki przedstawione poniżej.
Czas obcinania w [s] Tabela 1.4. Zestawienie czasów obcinania odcinka w zależności od liczby odcinanych odcinków Wielkość Czas w sekundach okna w % CS CSDRG CSDRGI ZESTAW I 1, 2,25 2,31 1,98 95,935 3,18 2,8 2,48 83,673 3,68 3,8 2,69 61,1713 3,74 3,2 2,63 31,747 3,35 2,75 2,42 15,6533 3,8 2,52 2,14 12,464 2,96 2,47 2,8 9,2797 2,91 2,42 2,9 6,1533 2,81 2,36 2,3 3,267 2,75 2,31 1,98 1,533 2,64 2,25 1,98,763 2,64 2,25 1,92,37 2,63 2,19 1,92,15 2,63 2,19 1,92 4, 3,5 3, CS CSDRG CSDRGI 2,5 2, 1,5 1, 1, 1, 1,,1 Procent odcinków leżących w zakresie okna (skala logarytmiczna) Rys. 1.16. Wykres czasu obcinania przy pomocy procedur ClippCS, ClippCSDRG i ClippCSDRGI. Porównując otrzymane wyniki stwierdzamy, że procedura ClippCSDRG jest ok. 15% szybsza od procedury ClippCS. Natomiast procedura ClippCSDRGI jest szybsza w stosunku do ClippCSDRG również o 15%. Stosowanie procedury ClippCSDRGI w sumie daje wyniki ok. 3% lepsze od bezpośredniej realizacji algorytmu Cohena-Sutherlanda przy pomocy procedury ClippCS. Widząc na podstawie przeprowadzonych testów jakie korzyści wnosi testowanie początkowe końców odcinków w celu jego bezpośredniego zaakceptowania lub odrzucenia, postanowiono testowanie z procedury ClippCSDRGI wprowadzić do procedur ClippCB i ClippLB realizujących algorytmy odpowiednio Cyrusa-Becka i Lianga-Barsky ego. Dzięki takiej modyfikacji unikniemy niepotrzebnych obliczeń w przypadku kiedy odcinek będzie mógł być bezpośrednio zaakceptowany lub odrzucony. Procedury ClippCBI oraz ClippLBI realizujące omówione modyfikacje mają następującą postać. Function ClippCBI(var x1,y1,x2,y2:real;xmin,ymin,xmax,ymax:real):boolean; var t,te,tl,dx,dy:real;p,q:array [1..4] of real;i:integer;k1,k2:byte; ClippCBI:=false;{wyznaczanie kodu i ewentualne odrzucenie odcinka}
if y1<ymin then if y2<ymin then exit else k1:=1 else if y1>ymax then if y2>ymax then exit else k1:=2 else k1:=; if x1<xmin then if x2<xmin then exit else if x2>xmax then k2:=8 else k2:=; k1:=k1 or 4; end else if x1>xmax then if x2>xmax then exit else if x2<xmin then k2:=4 else k2:=; k1:=k1 or 8; end else if x2<xmin then k2:=4 else if x2>xmax then k2:=8 else k2:=; if y2<ymin then k2:=k2 or 1 else if y2>ymax then k2:=k2 or 2; {koniec wyznaczania kodu punktów końcowych} te:=;tl:=1;dx:=x2-x2;dy:=y2-y1;p[1]:=dx;p[2]:=dy;p[3]:=-dx;p[4]:=-dy; q[1]:=xmax-x1;q[1]:=ymax-y1;q[3]:=x1-xmin;q[4]:=y1-ymin; for i:=1 to 4 do if p[i]= then if q[i]< then exit else continue; t=q[i]/p[i];if p[i]< then if t>te then te:=t else else if t<tl then tl:=t; if (te>tl) then exit; x2:=x1+tl*dx;y2:=y1+tl*dy;x1:=x1+te*dx;y1:=y1+te*dy;clippcbi:=true; Function ClippLBI(var x1,y1,x2,y2:real;xmin,ymin,xmax,ymax:real):boolean; var t,te,tl,dx,dy:real;p,q:array [1..4] of real;i:integer;k1,k2:byte; ClippLBI:=false;{wyznaczanie kodu i ewentualne odrzucenie odcinka} if y1<ymin then if y2<ymin then exit else k1:=1 else if y1>ymax then if y2>ymax then exit else k1:=2 else k1:=; if x1<xmin then if x2<xmin then exit else if x2>xmax then k2:=8 else k2:=; k1:=k1 or 4; end else if x1>xmax then if x2>xmax then exit else if x2<xmin then k2:=4 else k2:=; k1:=k1 or 8; end else if x2<xmin then k2:=4 else if x2>xmax then k2:=8 else k2:=; if y2<ymin then k2:=k2 or 1 else if y2>ymax then k2:=k2 or 2; {koniec wyznaczania kodu punktów końcowych} te:=;tl:=1;p[1]:=dx;p[2]:=dy;p[3]:=-dx;p[4]:=-dy; q[1]:=xmax-x1;q[1]:=ymax-y1;q[3]:=x1-xmin;q[4]:=y1-ymin; for i:=1 to 4 do if p[i]= then if q[i]< then exit else continue; t=q[i]/p[i]; if p[i]< then if t>tl then exit else if t>te then te:=t else else if t<te then exit else if t<tl then tl:=t; x2:=x1+tl*dx;y2:=y1+tl*dy;x1:=x1+te*dx;y1:=y1+te*dy;clipplbi:=true; Realizując omawiane wcześniej testy przy pomocy procedur ClippCSDRGI, ClippCBI oraz ClippLBI otrzymujemy następujące wyniki.
Czas rysowania w [s] Czas rysowania w [s] Tabela 1.5. Zestawienie czasów obcinania w zależności od liczby obcinanych odcinków Wielkość Czas w sekundach okna w % CBI LBI CSDRGI ZESTAW I 1, 2,3 2,3 1,98 95,93 4,23 4,4 2,48 83,55 4,83 5,5 2,69 61,195 4,44 4,62 2,63 31,7634 3,63 3,63 2,42 15,6414 3,8 3,2 2,14 12,4482 2,97 2,97 2,8 9,2656 2,85 2,85 2,8 6,1278 2,74 2,7 2,3 3,228 2,69 2,63 1,98 1,522 2,64 2,53 1,98,7538 2,58 2,53 1,92,328 2,58 2,52 1,92,1492 2,58 2,47 1,92 a) 6, 5, 4, 3, 2, CBI LBI CSDRGI 1,, 1, 1, 1,,1 Procent odcinków leżących w zakresie okna (skala logarytmiczna) b) 6, 5, 4, 3, 2, CBI LBI CSDRGI 1,, 1, 8, 6, 4, 2,, Procent odcinków leżących w zakresie okna Rys. 1.17. Wykresy czasu obcinania (I zestaw danych) w zależności od liczby odcinków z zakresie okna
Czas obcinania w [s] Czas obcinania w [s] Tabela 1.6. Zestawienie czasów obcinania w zależności od wielkości okna Wielkość Czas w sekundach okna w % CBI LBI CSDGI ZESTAW I 1. 2.3 2.3 1.98 64. 4.23 4.4 2.48 36. 4.83 5.5 2.69 16. 4.44 4.62 2.63 4. 3.63 3.63 2.42 1. 3.8 3.2 2.14.64 2.97 2.97 2.8.36 2.85 2.85 2.8.16 2.74 2.7 2.3.4 2.69 2.63 1.98.1 2.64 2.53 1.98.25 2.58 2.53 1.92.4 2.58 2.52 1.92.1 2.58 2.47 1.92 a) 6. 5. 4. 3. 2. CBI LBI CSDGI 1.. 1. 1. 1..1.1.1.1 Wielkość okna w % (skala logarytmiczna) b) 6. 5. 4. 3. 2. CBI LBI CSDGI 1.. 1. 8. 6. 4. 2.. Wielkość okna w % Rys. 1.18. Wykresy czasu obcinania (I zestaw danych) w zależności od wielkości okna
Czas obcinania w [s] Tabela 1.7. Zestawienie czasów obcinania uzyskanych zmodyfikowanymi algorytmami Algorytmy wyjściowe Algorytmy zmodyfikowane Wielkość Czas w sekundach Czas w sekundach okna w % CB LB CS CBI LBI CSDRGI 1. 4.83 5.6 2.31 2.3 2.3 2.3 Zestaw II 64. 4.83 4.61 2.31 1.87 1.87 1.87 36. 4.78 4.17 2.3 1.71 1.75 1.7 16. 4.78 3.85 2.25 1.59 1.6 1.53 4. 4.78 3.52 2.25 1.49 1.48 1.48 1. 4.78 3.46 2.25 1.48 1.48 1.48.64 4.78 3.41 2.2 1.48 1.48 1.48.36 4.78 3.4 2.2 1.48 1.48 1.48.16 4.78 3.35 2.2 1.48 1.48 1.43.4 4.78 3.35 2.2 1.43 1.48 1.43.1 4.78 3.35 2.2 1.43 1.43 1.43.25 4.78 3.35 2.2 1.43 1.43 1.43.4 4.78 3.35 2.2 1.43 1.43 1.43.1 4.78 3.35 2.2 1.43 1.43 1.42 5.5 5. 4.5 4. 3.5 3. 2.5 2. 1.5 1. 1. CB LB CS CSDRGI 1. 1..1.1.1 Wielkość okna w % (skala logarytmiczna).1 Rys. 1.19. Wykresy czasu obcinania (II zestaw danych) w zależności od wielkości okna Na wykresach odnoszących się do drugiego zestawu danych (rysunek 1.19) przedstawiono tylko zależność czasu obcinania od wielkości okna dla procedury ClippCSDRGI, gdyż jak wynika to z tabeli 1.7 czasy dla innych procedur są prawie identyczne. Wynika stąd ważny wniosek, że przy równomiernie rozłożonych odcinkach każda z ostatecznych postaci procedur jest dostatecznie skuteczna. W tabeli i na wykresach oprócz przedstawienia czasów algorytmów zmodyfikowanych przedstawiono również czasy wyjściowe w celu zaprezentowania zysku czasowego osiągniętego przez wprowadzone modyfikacje. Z przedstawionego porównania wynika, że najmniej na wprowadzonych modyfikacjach zyskał algorytm Cohena-Sutherlanda, a najwięcej Cyrusa-Becka, w którym był bardzo słaby mechanizm odrzucania lub akceptacji odcinków w całości.