• Rezultati Niso Bili Najdeni

5 Izdelava modela za generiranje funkcij in konˇ cnega vmesnika

5.1 Uvod

V tem poglavju je opisana izdelava modela za generiranje prenosnih funkcij in uporabniˇskega vmesnika, s katerim smo model implementirali v ogrodje VPT.

Uporabnik je lahko preko uporabniˇskega vmesnika v aplikaciji izbiral med pe-timi prenosnimi funkcijami, ki mu jih je predlagal model. Te funkcije je model izbiral na podlagi prenosnih funkcij, shranjenih v podatkovni bazi SQLite. S pomoˇcjo modela in pripadajoˇcega vmesnika je imel uporabnik veˇc nadzora pri upodabljanju ˇzelenega volumna.

Aplikacija VPT je znova potrebovala nekaj prilagoditev. Model je za svoje delovanje najprej potreboval trenutno prenosno funkcijo, s katero je bil izrisan volumen. Na podoben naˇcin kot v poglavju 4 smo podatke o prenosni funkciji preko mnogih funkcij in razredov s pomoˇcjo zahteve POST poslali na streˇznik.

Nato smo priˇceli z obdelavo shranjenih podatkov in izdelavo modela, ki je deloval na streˇzniku. S prvo skripto smo iz podatkovne baze SQLite izluˇsˇcili podatke o prenosnih funkcijah, jih obdelali in pripravili za uporabo v modelu. V drugi skripti smo implementirali sam model za generiranje prenosnih funkcij z metodo glavnih komponent s pomoˇcjo teh shranjenih podatkov. S skripto smo prebrali trenutno prenosno funkcijo, opravili analizo in predlagali pet novih prenosnih funkcij. Te je streˇznik poslal nazaj odjemalcu, kjer je bilo treba dodatne funkcije ˇse poslati uporabniˇskemu vmesniku. Na vmesniku smo za vsako prenosno funkcijo dodali nov gumb, ki je ob kliku prenosno funkcijo izrisal na platnu.

22 Izdelava modela za generiranje funkcij in konˇcnega vmesnika

5.2 Poˇ siljanje prenosne funkcije na streˇ znik

Znova smo zaˇceli z zaˇcetno razliˇcico aplikacije VPT. Ta je zdaj vsebovala tudi mnoge napake, ki smo jih med izdelavo prejˇsnje aplikacije in vmesnika odpravili.

Popravke smo tako le prenesli na to razliˇcico aplikacije, s ˇcimer smo v aplikaciji:

• odpravili napako pri meˇsanju barv na orodju za prenosne funkcije,

• dodali gumb Delete Bump na orodju za prenosne funkcije,

• odpravili napako pri prehajanju polj izven platna na orodju za prenosne funkcije in

• popravili nalaganje volumnov v funkciji handleVolumeLoad().

Po teh popravkih smo v aplikacijo dodali nalaganje 17 volumnov, prenosne funkcije katerih smo zbirali. Tokrat smo ˇzeleli, da bi uporabniki lahko izbirali, kateri volumen se bo naloˇzil v sceno. Nekaj podobnega je delala moˇznost Demo na prvi strani uporabniˇskega vmesnika, ki je seznam volumnov prebrala iz dato-teke demo-volumes.json in volumne prikazala kot spustni meni na vmesniku. Ta datoteka je aplikaciji manjkala, zato smo ustvarili novo in vanjo vnesli podatke o 17 volumnih, s katerimi smo delali prej. Datoteko in pripadajoˇce volumne smo premaknili v mapo build in seznam izbire volumnov se je prikazal na vmesniku aplikacije, kot prikazuje slika 5.1.

Seznam je sicer deloval, vendar je ob pritisku na gumb Load prihajalo do na-pake, zaradi katere se volumni niso nalagali v sceno. Za nalaganje volumnov preko opcije Demo je bila odgovorna funkcija handleLoadDemo() v razredu VolumeLo-adDialog. Ta je informacije o volumnu prejela iz datoteke demo-volumes.json, s prejetimi parametri pa sproˇzila funkcijo handleVolumeLoad() v razredu Applica-tion. Teˇzava je bila v tem, da smo za pravilni izris volumnov potrebovali tudi podatke o njihovih dimenzijah in razmerij velikosti vokslov, ki jih sestavljajo.

Te parametre smo dopisali v datoteko demo-volumes.json in popravili funkcijo handleLoadDemo(), da je podatke prebrala in posredovala funkciji handleVolu-meLoad(). Ob ponovnem zagonu je aplikacija zdaj naˇse volumne tudi pravilno izrisala.

5.2 Poˇsiljanje prenosne funkcije na streˇznik 23

24 Izdelava modela za generiranje funkcij in konˇcnega vmesnika

Naslednji korak je bilo poˇsiljanje podatkov o prenosni funkciji na streˇznik.

Tu smo si lahko pomagali s kodo, ki smo jo napisali za aplikacijo in vmesnik za zbiranje podatkov o prenosnih funkcijah. Uporabili smo enak pristop, kjer smo v razrede TransferFunctionWidget, MCMRendererDialog in Application na enaka mesta postavili klice funkcij trigger() in addEventListener(). Za vsako spremembo funkcije v orodju za spreminjanje prenosnih funkcij smo tako sproˇzili dogodek ’tool’, v nadrejenem razredu pa smo vsak dogodek preprosto poslali na-prej. Ko je dogodek prepoznal razred Application, je bilo treba parametre le ˇse poslati na streˇznik. Znova smo ustvarili razred Communicator, v katerem je potekala vsa komunikacija s streˇznikom. Znotraj razreda smo dodali funkcijo tool-SendTF(), ki je s pomoˇcjo vmesnika XMLHttpRequest poˇsiljala zahteve POST na streˇznik. V razredu Application smo nato ob vsakem dogodku ’tool’ poklicali funkcijo toolSendTF() s spremenljivko bumps, v kateri so se shranjevali podatki o trenutno aktivni prenosni funkciji. Funkcija toolSendTF() je v obliki zahteve POST podatke le ˇse poslala na streˇznik.

V datoteki server-node.js smo znova uporabili nekaj kode, ki smo jo napisali v prvi razliˇcici aplikacije za obvladovanje zahtev POST. Zdaj je bilo treba prido-bljene podatke posredovati skripti, kjer smo nameravali te podatke analizirati. Za testiranje komunikacije smo ustvarili testno skripto test.py, katere namen je bil samo branje in izpisovanje prejetih podatkov. Komunikacijo s skripto smo vzpo-stavili s pomoˇcjo modula child-process, ki vsebuje orodja za zaganjanje zunanjih procesov znotraj okolja NodeJS. Na objektu pythonProcess smo poklicali pripa-dajoˇco funkcijo spawn() s parametrom, ki je opisoval lokacijo datoteke test.py.

Ta klic je skripto uspeˇsno zagnal. Ker smo ˇzeleli v skripto poslati tudi podatke o prenosnih funkcijah, smo prilagodili klic funkcije spawn() in vkljuˇcili parameter bumps.

V skripti test.py smo ˇzeleli vnesene podatke prebrati in jih vrniti datoteki server-node.js. To smo storili s pomoˇcjo nameˇsˇcenega paketa sys, ki ima dostop do ukazne vrstice, s katero smo skripti posredovali podatke. S tem paketom smo z ukazom x = sys.argv[1] v spremenljivko x znotraj skripte uspeˇsno shranili podatke o prenosnih funkcijah. Za uspeˇsen preizkus komunikacije smo podatke le ˇse poslali nazaj na streˇznik. To smo tudi storili s pomoˇcjo paketa sys. Podatke je bilo treba najprej izpisati v terminalu s klicem funkcije print(), na koncu pa smo klicali ˇse funkcijo sys.stdout.flush(), ki je izpisane podatke preko ukazne

5.3 Izdelava Python skripte za analizo podatkov iz podatkovne baze 25

vrstice posredovala naprej. V datoteki server-node.js smo posredovane podatke ˇse prebrali. Na objektu pythonProcess smo poklicali funkcijo stdout.on(), ki nam je v parameter data shranila izpisane podatke. Podatke smo z uporabo funkcije console.log() tudi uspeˇsno izpisali, kar je pomenilo, da je komunikacija med streˇznikom in skripto vzpostavljena.

5.3 Izdelava Python skripte za analizo podatkov iz podat-kovne baze

Za zaˇcetek je bilo treba podatke iz podatkovne baze prebrati s Python skripto in jih obdelati z metodo PCA. Rezultate obdelave smo potrebovali za pravilno delovanje modela. Ustvarili smo novo skripto z imenom main.py, ki je prebrala podatke o prenosnih funkcijah iz datoteke test.db, jih obdelala z metodo PCA, model pa shranila v datoteko data.npy.

Pri branju podatkov smo si pomagali s paketom sqlite3, ki nam je omogoˇcal laˇzje delo z datoteko test.db. Za zaˇcetek smo s funkcijo sqlite3.connect() odprli datoteko, s klicem funkcije cursor() pa smo bazi priredili kazalnik, s katerim smo lahko izvajali poizvedbe SQL. Takˇsno poizvedbo smo izvedli v zanki, s katero smo zaobjeli vse elemente v tabeli Functions, kjer so se nahajale prenosne funkcije.

Vsako prenosno funkcijo smo nato individualno obravnavali.

Na tej toˇcki smo opazili, da so doloˇceni zapisi v podatkovni bazi za analizo neprimerni. Aplikacija je namreˇc v bazo shranjevala tudi prenosne funkcije, ki nastanejo takoj ob vnosu prvega barvnega polja ob kliku gumba Add Bump. Prve prenosne funkcije vsake seje so bile tako identiˇcne in niso bile rezultat uporabni-kovega dela, zato jih je bilo treba izloˇciti. Prav tako smo izloˇcili zapise, kjer je aplikacija shranila prazno tabelo barvnih polj, kar pomeni, da na platnu ni bilo nobenega barvnega polja.

Naleteli smo na novo teˇzavo. Zapisi iz podatkovne baze so se razlikovali po ˇstevilu barvnih polj, ki so opisovala prenosne funkcije. Vsako barvno polje je bilo

26 Izdelava modela za generiranje funkcij in konˇcnega vmesnika

• 2 parametra za viˇsino in dolˇzino polja,

• 2 parametra za poloˇzaj glede na x in y os platna,

• 4 parametre za vrednosti RGBA (barvo in prosojnost).

Ce so se prenosne funkcije razlikovale po ˇstevilu barvnih polj, so se razlikovaleˇ tudi po ˇstevilu parametrov, ki te funkcije definirajo. Ker smo prenosne funkcije nameravali analizirati s pomoˇcjo metode PCA je razliˇcno ˇstevilo parametrov pov-zroˇcalo teˇzavo. Za uporabo te metode smo namreˇc potrebovali nabor podatkov z enakim ˇstevilom parametrov, kar pa ni bilo izvedljivo za nabor funkcij nobenega izmed 17 volumnov. Prenosne funkcije bi lahko analizirali glede na volumen, ki ga opisujejo in ˇstevilo barvnih polj v prenosni funkciji, vendar smo se zaradi manjˇsega ˇstevila prenosnih funkcij pri nekaterih volumnih odloˇcili za drugaˇcen pristop. Vse prenosne funkcije z veˇc kot enim barvnim poljem smo razbili na to-liko novih prenosnih funkcij, kot je bilo barvnih polj. Iz vsake prenosne funkcije z dvema barvnima poljema sta tako nastali dve novi prenosni funkciji, enako smo naredili tudi za funkcije s tremi barvnimi polji.

Skripta je z zanko eno za drugo prebrala vse prenosne funkcije iz podatkovne baze. Vsak neprimerni zapis smo takoj odstranili, vse ostale pa smo prebrali s pomoˇcjo paketa simplejson(). Z uporabo funkcije simplejson.loads() smo niz znakov, ki je opisoval prenosno funkcijo pretvorili v seznam objektov, kjer je vsak objekt predstavljal svoje barvno polje. Nato smo z novo zanko individualno obravnavali vsako barvno polje, iz njega izluˇsˇcili relevantne parametre in jih shra-nili v nov seznam. Ta seznam smo pripeli seznamu megalist, kamor smo shrashra-nili vse prenosne funkcije in jih loˇcili glede na volumen, ki ga opisujejo.

Za konec smo podatke obdelali z metodo PCA, za kar smo uporabili paket sklearn[19]. V seznamu megalist smo izbrali prenosne funkcije enega izmed volu-mnov in izvedli ukaz pca.fit transform(), ki je na teh prenosnih funkcijah izvedel metodo PCA. Postopek smo v zanki ponovili za prenosne funkcije vsakega volu-mna iz seznama megalist. Transformacijo PCA za vsak volumen smo shranili v datoteko data.npy, pri ˇcemer smo obdrˇzali le dve glavni komponenti.

5.4 Uporaba modela za generiranje prenosnih funkcij 27

5.4 Uporaba modela za generiranje prenosnih funkcij

Z uporabo modela smo ˇzeleli generirati take prenosne funkcije, ki bi pripomogle h kvalitetni upodobitvi volumnov. Za te potrebe smo ustvarili novo skripto z imenom ok.py, v kateri smo definirali delovanje modela. Datoteka se je nahajala na streˇzniku, preko katerega je model komuniciral z aplikacijo. Vhodni poda-tek modela je predstavljala trenutno aktivna prenosna funkcija v aplikaciji VPT.

Prenosna funkcija je vsebovala podatke o barvnih poljih na platnu, ki jih je de-finiral uporabnik preko uporabniˇskega vmesnika. Aplikacija je podatke sporoˇcila na streˇznik, v datoteki ok.py pa smo podatke prebrali preko ukazne vrstice.

Za zaˇcetek smo v primeru, da je uporabnik definiral veˇc kot eno barvno polje, te zdruˇzili v en vektor. Novonastali vektor je predstavljal aritmetiˇcno sredino barvnih polj v prenosni funkciji. Iz datoteke data.npy smo v skripto uvozili tudi model PCA, ki smo ga izdelali na prenosnih funkcijah iz podatkovne baze. Vektor uporabnikove prenosne funkcije smo nato preslikali s shranjenim modelom PCA, ki nam je vektor z osmimi spremenljivkami preslikal v vektor z dvema spremen-ljivkama. Nato smo iz latentnega prostora modela PCA poiskali pet vektorjev, ki so po evklidski razdalji leˇzali najbliˇzje preslikanemu vektorju. Izbrane vektorje smo z inverzno transformacijo preslikali nazaj v parametrizirane prenosne funkcije z osmimi parametri. Funkcije smo shranili na seznam, ki je predstavljal seznam predlaganih prenosnih funkcij modela. Za konec smo seznam preko ukazne vrstice poslali v datoteko server-node.js.

5.5 Poˇ siljanje novih funkcij do vmesnika

V datoteki server-node.js smo nove prenosne funkcije sprejeli in jih poslali odje-malcu. Na odgovor smo ˇcakali s klicem funkcije stdout.on() na objektu python-Process, ki je dobljene prenosne funkcije shranjeval v spremenljivko data. Ko-munikacija od streˇznika do odjemalca poteka preko odzivov na zahteve, zato smo odgovor poslali z ukazom response.end(), kamor smo vstavili seznam prenosnih funkcij.

28 Izdelava modela za generiranje funkcij in konˇcnega vmesnika

izdelali funkcijo toolSendTF(), kjer smo tudi sprejeli odgovor streˇznika. Z upo-rabo objekta XMLHttpRequest to storimo z ukazom onreadystatechange, ki proˇzi dane ukaze vsakiˇc, ko se spremeni status zahteve. Znotraj te funkcije smo tako definirali, da naj sprejme odgovor responsetext takrat, ko bo zahteva uspeˇsno za-kljuˇcena. V responsetext smo tako prejeli odgovor streˇznika, ki smo ga s pomoˇcjo callback funkcije poslali nazaj v razred Application. Tam smo izdelali novo funk-cijo handleSendBumps(), ki je nove prenosne funkcije poˇsiljala v razred Transfer-FunctionWidget.

V razredu TransferFunctionWidget smo zato potrebovali veˇc funkcionalnosti, ki bodo urejale nastavljanje novih prenosnih funkcij. Razred Application je te najprej poslal v novo funkcijo applyNewBumps, kjer smo dobljene prenosne funk-cije s pomoˇcjo JSON.parse() pretvorili v seznam. V konstruktorju razreda smo dodali novo spremenljivko newbumps, kamor smo ta seznam shranili. Potrebovali smo ˇse funkcijo addSpecificBump(), ki smo jo zgradili na podlagi funkcije add-Bump(). Ta je urejala dodajanje novih barvnih polj na sredino platna ob kliku gumba Add Bump. Naˇsa funkcija je izrisala takˇsno polje, kot jo je specificirala prenosna funkcija iz modela, ki smo jo vnesli kot parameter pri klicu funkcije.

Zadnji korak dela je bila povezava novih funkcij z uporabniˇskim vmesnikom.

V HTML in CSS datoteki, ki sta definirali izgled vmesnika, smo dodali pet gum-bov tik pod platno na orodju za prenosne funkcije. Na koncu smo v konstruktorju razreda TransferFunctionWidget dodali potrebne posluˇsalce addEventListener() za vseh pet gumbov in jih povezali s funkcijo addSpecificBump(). Ob ponov-nem zagonu aplikacije so gumbi delovali, izrisovale so se nove prenosne funkcije.

Konˇcno delovanje aplikacije je prikazano na sliki 5.2.

5.5 Poˇsiljanje novih funkcij do vmesnika 29

30 Izdelava modela za generiranje funkcij in konˇcnega vmesnika

6 Rezultati

6.1 Rezultati aplikacije za zbiranje podatkov

Naloga aplikacije in vmesnika, prikazanega na sliki 4.6 je bila zbiranje podat-kov o prenosnih funkcijah. Podatke smo zbirali s pomoˇcjo uporabnikov, ki so aplikacijo uporabljali za upodabljanje nakljuˇcno izbranega volumna. Izbrali smo ˇsirok nabor raznolikih uporabnikov. Veˇcina uporabnikov je bila mlajˇsa od 25 let, najmlajˇsi je ˇstel 16 let, najstarejˇsi pa 56. Uporabniki so se tudi razlikovali v stopnji raˇcunalniˇske razgledanosti. Bolj veˇsˇcim uporabnikom smo zato le poslali povezavo do aplikacije in jim svetovali, naj z uporabo orodja poskusijo izrisati karseda lepo upodobitev danega volumna. Z doloˇcenimi manj veˇsˇcimi uporabniki smo njihovo uporabo aplikacije spremljali, v nekaterih primerih tudi ponudili do-datno razlago delovanja vmesnika (npr. razlaga delovanja gumbov). Tudi v tem primeru smo uporabnike spodbudili, naj vmesnik uporabijo tako, da ˇcim lepˇse upodobijo volumen na zaslonu.

Aplikacija je prenosne funkcije zbirala pribliˇzno teden dni. V tem ˇcasu se je v podatkovni bazi zbralo 2017 zapisov prenosnih funkcij iz 30 razliˇcnih sej.

Prenosne funkcije so bile shranjene za vseh 17 volumnov, ki smo jih naloˇzili v aplikacijo. ˇStevilo shranjenih funkcij za vsak volumen je moˇcno variiralo, kar je vidno na grafu 6.1.

Najveˇc prenosnih funkcij je bilo zbranih za volumen z zaporedno ˇstevilko 6, in sicer 347. Najmanj prenosnih funkcij je bilo zbranih za volumen 13, le 19 zapisov.

Teˇzava je bila v razliki med uporabniki, saj so nekateri uporabniki v kvalitetne upodobitve volumnov vloˇzili veˇc ˇcasa kot drugi. Bolj enakomerno porazdelitev podatkov bi dobili, ˇce bi bolje nadzirali proces uporabe aplikacije za zbiranje

32 Rezultati

Slika 6.1: Graf ˇstevila zapisov prenosnih funkcij v podatkovni bazi za razliˇcne volumne

podatkov. Idealno bi bilo, da bi za vse volumne imeli pribliˇzno podobno ˇstevilo prenosnih funkcij, saj bi analiza za vse volumne potekala bolj enakomerno.

Pred analizo prenosnih funkcij smo iz podatkovne baze odstranili prazne za-pise in zaza-pise tistih prenosnih funkcij, ki jih je izrisala aplikacija VPT ob pritisku gumba Add Bump, saj niso bili rezultat dela uporabnikov. To je ˇstevilo preno-snih funkcij zmanjˇsalo iz 2017 na 1904, naˇsli smo 113 neprimernih zapisov. Nabor prenosnih funkcij se je tako zmanjˇsal za 5,6 odstotka. Kasneje smo za potrebe analize prenosne funkcije z veˇc barvnimi polji razbili na manjˇse prenosne funkcije.

Povpreˇcno ˇstevilo barvnih polj v eni prenosni funkciji je znaˇsalo 1,66. Ko smo te funkcije razdelili, se je ˇstevilo prenosnih funkcij poveˇcalo na 3163. Podatke o novih prenosnih funkcijah za vsak volumen prikazuje 6.1.

Zanimalo nas je, kakˇsne prenosne funkcije so uporabniki shranjevali. S pomoˇcjo zajetih parametrov smo lahko za vsak volumen izrisali porazdelitev barvnih polj vseh funkcij, ki ta volumen opisujejo. Slika 6.3 prikazuje takˇsno porazdelitev na platnu za volumna aneurism.raw (zaporedna ˇstevilka 1) in csafe heptane.raw (zaporedna ˇstevilka 8).

6.1 Rezultati aplikacije za zbiranje podatkov 33

Slika 6.2: Graf ˇstevila zapisov prenosnih funkcij za analizo v modelu

Slika 6.3: Porazdelitev barvnih polj v prenosnih funkcijah volumnov 1 (na levi)

34 Rezultati

Iz teh porazdelitev je razvidno, da se je veˇcina uporabnikov za doloˇcanje kvalitetnih prenosnih funkcij odloˇcala, da bo barvna polja postavila na zgornjo stran platna. Tudi pri ostalih volumnih so porazdelitve barvnih polj sledile istemu vzorcu, kjer je zelo malo barvnih polj bilo postavljenih na spodnjo polovico platna.

Iz tega smo lahko sklepali, da se zgostitve podatkov v naˇsih volumnih nahajajo predvsem na zgornji strani platna. Iz grafov lahko tudi vidimo, da so na desni strani platna barvna polja vseh razliˇcnih oblik, na levi pa obiˇcajno najdemo le oˇzja barvna polja. Na teh obmoˇcjih so preˇsiroka barvna polja postala za upodobitve neuporabna, saj so izpostavila preveˇc ˇsuma v volumnu.

Opazili smo ˇse eno podrobnost. Veliko barvnih polj je bilo spremenjenih po ˇsirini, skoraj nobeno pa tudi po dolˇzini. Teˇzava je bila posledica manjkajoˇcega navodila na uporabniˇskem vmesniku, ki bi uporabnika seznanila z moˇznostjo spre-minjanja dolˇzine polja. To je v aplikaciji VPT sicer izvedljivo z pritisnjenim gumbom Shift in premikanjem koleˇsˇcka na miˇski.

Zbrane prenosne funkcije so tvorile osnovo za model generiranja prenosnih funkcij. Kvaliteto teh prenosnih funkcij smo lahko analizirali le s pomoˇcjo modela, ki je prenosne funkcije predlagal uporabniku.

6.2 Rezultati modela za generiranje prenosnih funkcij

Slika 5.2 prikazuje delovanje modela in pripadajoˇcega uporabniˇskega vmesnika za generiranje prenosnih funkcij. Ker je takih primerov uporabe veliko, smo delovanje modela tudi podrobneje ocenili. Zanimalo nas je, kako kvalitetno deluje model ob dodajanju razliˇcnega ˇstevila novih barvnih polj na platno.

Za zaˇcetek smo ocenjevali delovanje modela pri dodajanju prvega barvnega polja. Ko uporabnik v aplikaciji naloˇzi nov volumen v sceno, najprej pritisne na gumb Add Bump, ki predstavlja zaˇcetno razliˇcico prenosne funkcije. Na sredini platna se izriˇse okroglo barvno polje rdeˇce barve. Zaˇcetna razliˇcica prenosne funkcije je za upodabljanje naˇsih volumnov povsem neuporabna, saj volumna v sceni ne uspe kvalitetno upodobiti. S klikom na enega izmed novih gumbov model generira novo prenosno funkcijo in jo izriˇse na platnu, kot kaˇze slika 6.4.

6.2 Rezultati modela za generiranje prenosnih funkcij 35

Slika 6.4: Prvi primer uporabe modela za generiranje prenosnih funkcij za izris volumna coronal mal.raw.

Rezultat, kot ga kaˇze slika 6.4, smo dobili s klikom na gumb 1. TF. Z enim klikom gumba je uporabnik s pomoˇcjo modela izrisal dovolj kvalitetno upodobitev volumna, ki prikazuje vse njegove glavne lastnosti. Rezultate podobne kvalitete smo dobili, ˇce je uporabnik izbral katerega izmed ostalih ˇstirih gumbov, postopek pa je deloval kvalitetno tudi pri upodabljanju drugih volumnov. V teh primerih se

Rezultat, kot ga kaˇze slika 6.4, smo dobili s klikom na gumb 1. TF. Z enim klikom gumba je uporabnik s pomoˇcjo modela izrisal dovolj kvalitetno upodobitev volumna, ki prikazuje vse njegove glavne lastnosti. Rezultate podobne kvalitete smo dobili, ˇce je uporabnik izbral katerega izmed ostalih ˇstirih gumbov, postopek pa je deloval kvalitetno tudi pri upodabljanju drugih volumnov. V teh primerih se