26.07.2013 Views

Datalogi 0GB K-opgaven: DIKU Flight Simulator 2004

Datalogi 0GB K-opgaven: DIKU Flight Simulator 2004

Datalogi 0GB K-opgaven: DIKU Flight Simulator 2004

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Datalogi</strong> <strong>0GB</strong> K-<strong>opgaven</strong>: <strong>DIKU</strong> <strong>Flight</strong> <strong>Simulator</strong> <strong>2004</strong><br />

Svend Ezaki Tofte, Andres Eskjær og Troels Parbst<br />

13. maj 2003<br />

2


Indhold<br />

1 Sammenfatning 5<br />

2 Problemorienteret analyse 5<br />

2.1 Programdomæne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />

2.1.1 Modellens koncepter . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6<br />

2.1.2 Figurene og deres udregninger . . . . . . . . . . . . . . . . . . . . . . 6<br />

2.1.3 Forbehold ved udregningerne . . . . . . . . . . . . . . . . . . . . . . . 6<br />

2.2 Mulige fejl for systemet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />

2.3 Krav . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />

2.3.1 Krav til inddata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />

2.3.2 Krav til uddata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />

2.3.3 Øvrige krav . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />

3 Objektorienteret design 10<br />

3.1 Foranalyse til det objektorienterede design . . . . . . . . . . . . . . . . . . . . 11<br />

3.2 Dokumentation af det objektorienterede design . . . . . . . . . . . . . . . . . 11<br />

3.3 Analyse og diskussion af det objektorienterede design . . . . . . . . . . . . . . 12<br />

3.3.1 Generel struktur, Model-View-Controller . . . . . . . . . . . . . . . . . 12<br />

3.3.2 Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13<br />

3.3.3 View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13<br />

3.3.4 Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13<br />

3.3.5 Konklusion p˚a objektorienteret design . . . . . . . . . . . . . . . . . . 14<br />

3.3.6 Cyklisk process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />

3.3.7 Det objektorienteret design af domænet . . . . . . . . . . . . . . . . . 14<br />

3.3.8 Figur design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />

4 Programmeringsovervejelser 15<br />

4.1 Programstruktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15<br />

4.2 Programkørsel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />

4.2.1 Køretid for hovedalgoritmen . . . . . . . . . . . . . . . . . . . . . . . . 19<br />

5 Brugervejledning 19<br />

5.1 Anvendelse af tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />

6 Programbeskrivelse 21<br />

6.1 Kamera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />

7 Afprøvning 23<br />

7.1 Obligatoriske billeder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />

7.2 Matematisk udregning af nuance . . . . . . . . . . . . . . . . . . . . . . . . . 25<br />

7.3 Krav til opstilling i 3 dimensioner . . . . . . . . . . . . . . . . . . . . . . . . . 26<br />

7.4 XML krav . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28<br />

7.5 Konklusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />

3


A UML diagrammer 36<br />

A.1 Usecase diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36<br />

A.2 Klassediagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />

A.3 Sekvensdiagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38<br />

A.4 Sekvensdiagram for Scene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />

B CRC Kort 40<br />

C XML specifikation 54<br />

C.1 Krav til tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54<br />

D Afprøvningsdata 56<br />

D.1 Obligatoriske billeder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56<br />

D.2 Data til matematisk udregning af nuance . . . . . . . . . . . . . . . . . . . . 59<br />

D.3 Data til opstilling i 3 dimensioner . . . . . . . . . . . . . . . . . . . . . . . . . 60<br />

D.3.1 Test 3a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60<br />

D.3.2 Test 3b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60<br />

D.3.3 Test 3c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62<br />

D.3.4 Test 3d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63<br />

D.3.5 Test 3e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65<br />

D.3.6 Test 3f . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66<br />

D.3.7 Test 3g . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67<br />

D.3.8 Test 3h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69<br />

D.3.9 Test 3i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70<br />

E Kildekode 73<br />

E.1 Figur.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73<br />

E.2 Fly<strong>Simulator</strong>.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75<br />

E.3 Kamera.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76<br />

E.4 KameraVinkler.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79<br />

E.5 Kanvas.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80<br />

E.6 Kugle.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85<br />

E.7 Mesh.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88<br />

E.8 Plan.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90<br />

E.9 Punkt.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93<br />

E.10 Scene.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94<br />

E.11 Sol.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97<br />

E.12 Stoerrelsesfejl.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98<br />

E.13 Trekant.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99<br />

E.14 Vektor.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103<br />

E.15 XMLParseError.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105<br />

E.16 XMLParser.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106<br />

4


1 Sammenfatning<br />

Denne rapport er en besvarelse af Dat0Gb k-<strong>opgaven</strong> 2003, ”<strong>DIKU</strong> Fly<strong>Simulator</strong> <strong>2004</strong>”, skrevet<br />

af Andres Eskjær, Troels Parbst og Svend Ezaki Tofte.<br />

Opgaven gik ud p˚a at lave en flysimulator. Kun dele af en flysimulering skulle dog implementeres,<br />

mere specifikt skulle programmet kunne tegne et billede, af hvad piloterne s˚a ud af<br />

deres vindue. Billedet skulle tegnes ved en teknik kaldet str˚alesporing.<br />

Opgaveformuleringen og analysen har lagt grund for hvilken matematik, som er blevet<br />

implementeret i programmet. Udover teorien har analysen klarlagt de potentielle faldgrubber<br />

ved teorien, i en eventuel implementation.<br />

Design fasen har ledt frem til et godt objektorienteret design, som følger design mønstret<br />

Model-View-Controller. Dette isolere problemdomænet i et centralt omr˚ade, mens view abstrahere<br />

fra metoder og egenskaber i domænet, og blot afbildeder domænet.<br />

Programmet er blevet opstillet s˚aledes at problemstillinger bliver h˚andteret p˚a en ensartet<br />

m˚ade. Programmet er blevet opstillet uden at kompromitere korrektheden af de udregninger<br />

som programmet skal lave. Dette er yderligere bekræftet ved en udtømmende afprøvning,<br />

s˚aledes at programmet kalkulere den rigtige farve, og at domænets problemstillinger behandles<br />

korrekt.<br />

Programmet som er blevet skrevet, er den minimale løsning, per opgave formuleringen.<br />

Dette, koblet sammen med seperationen af designet, i model og view, gør at vi anser <strong>opgaven</strong><br />

for løst tilfredsstillende.<br />

2 Problemorienteret analyse<br />

Denne analyse vil dække en tolkning af opgaveteksten, kritiske punkter ved <strong>opgaven</strong> og vores<br />

beslutninger ved løsning af denne. Den vil præcisere krav til ind- og uddata, samt en<br />

række mere eller mindre formelle krav til programmets præstationer. Afsnittene er opdelt i<br />

programdomæne, forbehold ved udregningerne for til sidst at forklare kravene til programmet.<br />

Generelt omhandler <strong>opgaven</strong> str˚alesporing til grafisk anvendelse. Str˚alesporing er en teknik,<br />

der ved udnyttelse af rumgeometriske begreber, kan udregne et billede af et fiktivt rum,<br />

der indeholder matematisk formulerede figure, s˚asom kugler, planer, osv.. Billedets vinkel i<br />

forhold til det fiktive rum og pixel opløsning bestemmes af et ”kamera”, som ligeledes er<br />

matematisk formuleret. Programmet skal alts˚a kunne generere s˚adanne billeder, ud fra en<br />

formulering af et fiktivt rum, beskrevet vha. udvalgte matematisk beskrevede figurer.<br />

2.1 Programdomæne<br />

Str˚alesporing er et forsøg p˚a, at generere 3-dimensionelle afbildninger, som man kender dem<br />

fra et almindeligt kamera, men afbilleder faktisk kun rumgeometriske begreber under basale<br />

visuelle forholdregler. Derfor er det en naturlig del for forst˚aelsen, af udregningeprocessen - og<br />

dermed en kraftig indvirken p˚a letheden af programmets skabelse - at beskrive og repræsentere<br />

programmet i rumgeometriske termer. Forklaringerne i denne rapport vil ligeledes udtrykke<br />

sig i disse termer. En opsummering af de generelle termer kan ses p˚a [2] bilag B.<br />

P˚a trods af beslutningen om at repræsentere programmet rumgeometrisk, s˚a er en direkte<br />

oversættelse dog ikke mulig - p˚a grund af matematikkens uendeligheder og datamatens begrænsninger<br />

- og desuden s˚a er det ogs˚a kun en delmængde af rumgeometrien, det er relavant<br />

at beskrive for programmet. Dvs. at det der inddrages fra rumgeometrien kun er de væsentlige<br />

5


dele af begreberne, som skal reduceres til monotone beregninger, s˚aledes at en datamat har<br />

grundlag for at kunne anvende modellen.<br />

Det skal her præciseres, at det program vi ønsker at skabe, udelukkende skal fungere som<br />

en implementation af modellen, dvs. kunne udregne et billede ud fra formulering af et fiktivt<br />

rum fra - i dette tilfælde - en XML fil. Programmet skal ikke prøve at finde fornuft i en givet<br />

rum, eller p˚a nogen m˚ade forsøge at h˚andtere en mulig brugerfejl.<br />

2.1.1 Modellens koncepter<br />

Opgaven[2] fra afsnit 3.2 til 3.4 beskriver hvordan samspillet mellem øjepunktet, filmen og<br />

scenen fungere p˚a et generelt nivuau.<br />

Vi følger retningslinjerne fra [4], og opbygger vores model som deri formuleret.<br />

2.1.2 Figurene og deres udregninger<br />

De rumgeometriske grundformer som udvælges til programmet er planer, kugler, trekanter og<br />

en særlig form ”mesh”, som er en samling af trekanter.<br />

Kravet for at programmet kan h˚andtere en figur og dermed udregne dens fremtræden p˚a<br />

billedet er, at der for figurens vedkommende, kan fremstilles en matematisk formulering af,<br />

hvor figuren befinder sig i rummet. I praksis betyder det, at der skal fremstilles en formel<br />

til udregning af skæringspunkt, mellem den linje som forlænges ud igennem filmen fra øjet,<br />

og figuren. Kan en s˚adan formel fremstilles for en figur, eller samling af figurer, s˚a er det for<br />

systemet ikke nødvendigt at vide mere om figuren, n˚ar den skal lokaliseres i rummet. Det<br />

giver systemet en fleksibilitet overfor indførelsen af nye figurer.<br />

For grundformernes vedkommende s˚a har kuglen og planet simple ligninger, til udregning<br />

af skæringspunkter mellem dem, og en linje jf. <strong>opgaven</strong>[2] afsnit 3.6.1 og 3.6.2. Trekanten kan<br />

delvist udnytte at planet bliver defineret i programmet og anvende noget af dens funktionalitet,<br />

men skal yderligere beregne om skæringspunktet ligger inde i trekanten, hvilket sker jf.<br />

[2] afsnit 3.6.4.<br />

Den lidt specielle figur mesh, er af XML’en specificeret som en samling af trekanter, og<br />

det giver god mening at udnytte det i programmet. Dvs. at udregningsmetoderne for mesh’et<br />

er de samme som for trekanten.<br />

En anden ting programmet skal vide om figurene, er hvordan en nuance udregnes i et<br />

givent skæringspunkt. Nuancer udregnes jf <strong>opgaven</strong>[2] afsnit 3.5, men det skal tilføjes at vi<br />

vælger, at der for hver figur kun skal kunne tildeles en reflektionskoefficient, som er gældende<br />

for alle dens grundfarver.<br />

Der udregnes kun lys fra en enkelt punktformig lyskilde, og andre faktorer som f.eks.<br />

reflektionslys fra andre figurer eller flere lyskilder bliver ikke medtaget i udregningerne. Derfor<br />

behøves en nuance for en figur kun at udregnes, hvis den ikke bliver overskygget af en anden<br />

figur fra scenen. Vi vælger at den farve der tildeles punkter i billedet, hvor det gælder at<br />

linjen som forlænges ud igennem filmen som ikke rammer nogen figure, eller som rammer en<br />

figur som ligger i skygge af en anden figur, bliver helt sorte.<br />

2.1.3 Forbehold ved udregningerne<br />

I forsøget p˚a at overføre rumgeometrien til datamat anvendelse, opst˚ar der en række problemer<br />

i forbindelse med udregningerne.<br />

6


Ciffertab Som et typisk problem i forholdet mellem matematiske modeller og datamater, s˚a<br />

opst˚ar der et problem i forbindelse med ciffertab. Dette vil med ret stor sandsynlighed medføre<br />

nogle problemer ved sammenligning af punkter, da disse jo blot er tal. Beregningsmæssigt<br />

vil det nemlig være usandsynligt at to forskellige beregninger af samme skæringspunkt f˚ar<br />

de samme talværdier. Derfor kan datamatens talsammenligningen ikke anvendes, uden der<br />

indføres noget ’albuerum’ i systemet.<br />

Kameraet Skæringspunkterne mellem linien udspændt af øjet og et punkt i filmen, og en<br />

figur i scenen, skal ligge foran filmen, hvis de skal kunne ses.<br />

En væsentligt ting her er ogs˚a hvordan kameraet skal opfører sig. Alts˚a om det udelukkende<br />

skal opfattes matematisk, repræsenteret som et punkt og to vektorer, eller p˚a en mere<br />

virkelighedstro m˚ade. Vi vælger at programmet skal opfatte kameraet som et normalt kamera,<br />

og at figurere derfor ikke kan optræde imellen øjet og filmen.<br />

Hvis der er placeret figure mellem øje og film, s˚a vil de dele af figurerne, som skærer ind<br />

i filmen, bare blive ignoreret, og ikke fremtræde p˚a billedet. Ligger en kugle f.eks. placeret<br />

midt i filmen, s˚a vil kun den ene side af den kunne ses p˚a billedet.<br />

Forholdet mellem kameraet og lyskilden En vigtig ting at bemærke ved dette er, at<br />

lyskilden ikke tager højde for hvad kameraet ser. Alts˚a vil en udregning af et skæringspunkt<br />

mellem lyskilden og den kugle som ligger midt i filmen, blive gennemført, uden at tage stilling<br />

til om kameraet kan se det eller ej.<br />

En konsekvens af dette valg kan ses, hvis man ser p˚a den før omtalte kugle. Denne kugle<br />

vil blive ramt af linjen fra øjet i to punkter. Det første punkt vil blive vurderet til at være<br />

ugyldigt, da det ligger placeret inde i filmen. Det andet punkt, p˚a den anden side af kuglen,<br />

vil derimod være gyldigt, da det ligger udenfor filmen.<br />

Næste skridt er at finde ud af om lyskilden skærer dette punkt som det første p˚a sin linie<br />

imod det punkt som øjet skar.<br />

Antages der at lyskilden er placeret bag øjet, s˚a vil det første skæringspunkt mellem<br />

lyskilden og skæringspunktet som øjet fandt for gyldigt, ikke være det samme, da lyskilden<br />

godtager skæringspunktet fra første gang den skar kuglen.<br />

Resultatet af beregningen er, at de punkter hvor kuglen skær filmen, bliver sorte. Se<br />

figur 1.<br />

Nuanceberegning Et tredje problem opst˚ar ved udregning af nuancer. Den ligning vi<br />

anvender til udregning af lysintensitet ([2] side 7 nederst), er afhængig af vinklen mellem en<br />

figurs normalvektor og den vektor som findes mellem lyskilden og det skæringspunkt, hvor<br />

figuren er ramt. Er vinklen over 90 ◦ , s˚a er lysintensiteten 0%, og farven alts˚a sort.<br />

For at denne udregning skal give mening i forhold til kameraet, og alts˚a den nuance som<br />

ender p˚a billedet, s˚a er figurens normalvektor nødt til at pege imod øjet. Ud af dette fremg˚ar<br />

tydeligt, at der til ethvert punkt er knyttet en normalvektor, men at denne kan inverteres<br />

uden at det giver en matematisk forskel.<br />

Det er vigtigt at bemærke dette, da en monoton beregning af en normalvektor for f.eks.<br />

et plan, ikke tager højde for hvor et opdigtet punkt, som et ”øje”befinder sig.<br />

Desuden, s˚a kan den normalvektor som et kamera har brug for, være den modsatte af<br />

den som et andet kamera har brug for. Derfor er det nødvendigt at tage højde for dette ved<br />

7


sol<br />

skæringspunkt mellem<br />

lyskilde og kugle<br />

øje<br />

film<br />

kugle<br />

Fremtræden på billedet<br />

skæringspunkt mellem<br />

øje og kugle.<br />

Figur 1: Forbehold ved sol placeret uden for kugle<br />

hver nuanceberegning. For grundformernes vedkommende, s˚a er det ved dem alle, at dette<br />

forbehold skal tages.<br />

Det er oplagt at planet skal tage højde for dette, da dens normalvektor udregnes som<br />

krydsproduktet mellem de to vektorer som indg˚ar i planet, og at trekanten og mesh’et ligeledes<br />

skal tage højde for det, da de anvender funktionalitet fra planet.<br />

Kuglen skal dog ogs˚a tage højde for dette, da vi har valgt at der ikke m˚a forekomme figurer<br />

mellem øjet og filmen. Derfor s˚a kan der, som forklaret ovenst˚aende, forekomme situationer,<br />

hvor at det første skæringspunkt mellem øjet og kuglen, ikke bliver betragtet som gyldigt,<br />

men at det andet skæringspunkt er gyldigt.<br />

Det ændre den sædvanlige normalvektorberegning for en kugle, da man nu risikere at<br />

m˚aske skulle invertere normalvektoren, inden beregningerne fortsættes.<br />

Denne beslutning giver kuglen nogle særlige egenskaber hvis der sker et særligt samspil<br />

mellem den og lyskilden.<br />

Som før nævnt, s˚a tager lyskilden ikke højde for hvor filmen er placeret. Derfor s˚a bliver<br />

effekten af, at en kugle ligger placeret midt i filmen, at alle punkter hvor kuglen skærer ind i<br />

filmen, hvor man alts˚a s˚a at sige ser ind i kuglen, bliver sorte, hvis alts˚a lyskilden er placeret<br />

udenfor kuglen.<br />

Er lyskilden derimod placeret inde i kuglen, s˚a vil der p˚a billedet fremkomme indesiden af<br />

kuglen. Alts˚a bliver de første skæringspunkter mellem øjet og kuglen ignoreret af kameraet,<br />

og farverne fra de næste skæringspunkter udregnes.<br />

I alle disse skæringspunkter bliver den nuance som udregnes ikke sort, da lyskilden nu<br />

befinder sig inde i kuglen, og derfor registerer alle de skæringspunkter som kameraet har<br />

fundet som gyldige. Se figur 2 for grafisk opstilling af problemet.<br />

2.2 Mulige fejl for systemet<br />

Da vi ønsker at skabe et program, som kun kan udregne et billede ud fra nogle givne data, s˚a<br />

vil en tænkelig fejl, f.eks. at kameraet peger væk fra scenen, ikke blive betegnet som en fejl<br />

af programmet. Det vil være op til brugeren af programmet, at sikre sig at der er mening i<br />

scenens opbygning og kameravinklerne.<br />

Fejl som skal opfanges af programmet, er kun fejl som forhindre beregning af uddata, og<br />

kan opdeles i to grupper.<br />

8


sol<br />

film<br />

øjets og lyskildens<br />

skæringspunkt med<br />

kuglen<br />

normalvektor<br />

øje Fremtræden på billedet<br />

Figur 2: Forbehold ved sol placeret indeni kuglen<br />

Parser/Fil fejl er en gruppe fejl som eksistere, pga. <strong>opgaven</strong>s krav om at inddata skal formuleres<br />

i XML. Det er essentielt for programmet, at de data som bliver parset fra XML’en, er<br />

korrekte. Konstatere parseren fejl eller mangler i disse, s˚a stoppes beregningerne. En nærmere<br />

præcision af inddata bliver beskrevet senere.<br />

Fejl under programkørsel er fejl som fremkommer under udregning af uddata. Konstatere<br />

programmet en s˚adan fejl, stoppes beregningerne, da uddata vil blive forkert.<br />

2.3 Krav<br />

Her formuleres kort kravene til, hvordan inddata skal formuleres, hvordan uddata bliver formuleret,<br />

hvilke krav vi mener programmet skal opfylde, og hvilke egenskaber vi mener programmet<br />

skal have.<br />

2.3.1 Krav til inddata<br />

XML’en skal opfylde kravene som w3.org specificere i [5]. w3.org betegner den XML som<br />

programmet kræver som Wellformed, hvilket vil sige at den opfylder den formelle standard<br />

for formulering syntaktisk korrekt XML.<br />

Generelt for vores parser s˚a gælder det, at n˚ar parseren g˚ar ind i et tag, s˚a vil den søge<br />

efter de typer tags som den er defineret til at lede efter i det specifikke tag, og intet andet.<br />

Skal den f.eks. under et særligt tag bruge 4 tags af typen , da vil den undersøge alle de<br />

tags af typen som findes i første niveau af undertræet, og melde fejl hvis antallet af<br />

de eftersøgte tags er enten mere eller mindre end det p˚akrævede. Befinder der sig andre tags<br />

i undertræet end dem som er p˚akrævet, vil disse blive ignoreret. En detaljeret gennemgang<br />

af hvilke tags der er p˚akræves for at køre programmet, og hvad de enkelte tags kræver af<br />

undertags og attributter er specificeret i C.<br />

2.3.2 Krav til uddata<br />

[2] kræver at uddata sker i et billedformat ved navn .ppm, og i forbindelse med denne opgave<br />

sker det vha. en java klasse, Kanvas, som er stillet til r˚adighed. Vi har valgt at anvende Kanvas<br />

klassen, uden modifikationer.<br />

9


2.3.3 Øvrige krav<br />

De krav, ud over de formelle, som vi ser god mening at stille til programmet, er som før nævnt,<br />

at der ikke skal vises noget mellem øjet og filmen. Dette krav er begrundet som et perceptuelt<br />

krav, der skal hjælpe brugeren af programmet til at forst˚a kameraets rolle i modellen. Ved<br />

at forbyde at der findes nogen figurer mellem øjet og filmen, vil kameraet virke mere som et<br />

kamera fra virkeligheden, og være nemmere at arbejde med.<br />

Vi ønsker ligeledes at programmet tager højde for alle de ting, som er beskrevet i afsnittet<br />

omkring forbehold ved udregningerne.<br />

Ud over disse specifikke ting, der ønsker vi ogs˚a at programmet p˚a længere sigt skal være<br />

programmeringsmæssigt velovervejet, s˚aledes at der bliver god mulighed for at genbruge funktionalitet<br />

s˚a mange steder som muligt, og at programmet bliver fleksibelt overfor ændringer<br />

og udvidelser.<br />

Som en mindre ting ønsker vi ogs˚a, at der overfor brugeren bliver fremstillet en mindre<br />

brugerflade, s˚aledes at der kan ses hvor langt programmet er kommet i beregning af billedet.<br />

Der følger nu en liste af de formelle krav programmet skal opfylde:<br />

• Programmet skal skrives i programmeringssproget Java.<br />

• Indlæse inddata fra en fil, skrevet i XML.<br />

• Udskrive uddata til en fil, i ppm format, til en antal filer, beskrevet i XML’en.<br />

• Have en sceneopbygning best˚aende af et kamera, grundformerne beskrevet tidligere, og<br />

en punktformig lyskilde.<br />

• Programmet skal kunne køres p˚a <strong>DIKU</strong>’s EDB-system.<br />

3 Objektorienteret design<br />

Dette afsnit vil dokumentere og diskutere det objektorienterede design som vi er kommet<br />

frem til. Først vil vi formulere nogle objektorienterede ideer, som vi ønsker vores design skal<br />

reflektere. Sidenhen vil designet, som det er fremkommet efter designfasen blive opsummeret,<br />

med henvisninger til bilagende hvor de passende diagrammer kan findes. Til sidst vil vi, med<br />

afsnittets egentlige form˚al, gennemg˚a og diskutere det design, som vi er kommet frem til.<br />

Inden afsnittet g˚ar igang, kan det være fordelagtigt, at definere visse begreber, som ellers<br />

kan have en flydende betydning.<br />

Design bruges her om det færdige objektorienterede design, som det er fremkommet efter<br />

analysen.<br />

Systemet/Programmet er en færdig implementation af designet, med alle dets nødvendige<br />

delkomponenter.<br />

Domæne bruges her i sammenhæng til at benævne et systems kerneomr˚ade. I vores opgave<br />

er domænet rumgeometri. Dog er det vigtigt at ligge mærke til at i et program, kan der godt<br />

forekomme flere andre, deldomæner. Et domæne kunne f.eks. være brugerflade, eller ind og<br />

uddata h˚andtering.<br />

10


Modellen er en implementation af domænet, med de metoder og egenskaber som vi har<br />

fundet nødvendige at inkludere fra domænet.<br />

Repræsentationer bruges omkring konkrete klasser som repræsentere elementer i domænet.<br />

Kunne f.eks. være en klasse som repræsentere kuglen. Kan ligeledes bruge omkring matematiske<br />

koncepter, som punkter, osv.<br />

3.1 Foranalyse til det objektorienterede design<br />

Inden vi g˚ar igang med at finde designet, ønsker vi at formulere en række objektorienterede<br />

ideer, som vi ønsker programmet skal afspejle. Form˚alet med at fastsætte disse er, at give<br />

m˚ader til at anskue design fasen, ud over dem, som er angivet i ”Using UML”[6], og i Eric’s<br />

OOD ”kogebog”[1]. Dette vil forh˚abentlig give et endnu mere gennemført design, end ellers.<br />

Identificering af domænet i designet Vi ønsker at identificerer, de centrale klasser, som<br />

er vigtige for domænets virkem˚ade og egenskaber.<br />

Alle systemer definere, ud over det domæne som systemet arbejder i, nogle understøttelses<br />

klasser/kode. Typisk eksempel er fx. main indgangs punktet i et Java program. Det er vigtigt<br />

at identificere de klasser, som ikke er en del af problemdomænet.<br />

Design mønstre Vi ønsker at finde - hvor det er fordelagtigt - tydelige anvendelser af<br />

design mønstre. Især dem, som er blevet gennemg˚aet i pensum, og dem som vil hjælpe med<br />

adskillelse af domæne klasser, og understøttelses klasser.<br />

Sammenhold mellem design og virkelighed S˚a vidt muligt, skal designet afspejle en<br />

realitisk model, som var den fundet i virkeligheden. Dette for at lette forst˚aelse af vores<br />

design. Dette kan hjælpe med forst˚aelsen for b˚ade bruger (f.eks. visuel tekstbehandling i<br />

Microsoft Word), og med forst˚aelsen for eventuelle programmører, som senere skal opdatere<br />

programmet.<br />

Givet vil ikke alt i designet, kunne føres over fra virkeligheden. Det er f.eks. tydeligt, at<br />

et matematisk koncept som en vektor, ikke har en tilsvarende fysisk tilstedeværelse i virkeligheden.<br />

Her ønsker vi at følge de matematiske koncepter, og modelere domænet passende,<br />

s˚a det er logisk for domæneeksperter.<br />

3.2 Dokumentation af det objektorienterede design<br />

Usecase I bilag A.1 findes et diagram over den ene usecase, som programmet skal kunne<br />

h˚andtere. Denne ene usecase kaldes for Lav Billed.<br />

Klassediagram Bilag A.2 viser et diagram over klassernes generelle associationer og generaliseringer.<br />

Ligedes viser diagrammet navigation, af associationerne. Det er vigtigt at lægge<br />

mærke til at flere klasser er udeladt, for overskuelighedens skyld. F.eks. s˚a kender XMLParser<br />

klassen til alle klasser (med undtagelse af Kanvas og Stoerrelsesfejl). Ligeledes er Vektor<br />

og Punkt klassen udeladt, da disse primært bruges til at overføre informationer mellem klasserne,<br />

og de bruges derfor i mange af klasserne. Ligeledes er kun de essentielle attributter og<br />

metoder medtaget.<br />

11


Sekvens diagram for systemet I bilag A.3, ses et diagram over en program kørsel. Her<br />

vil der blive givet noget supplerende tekst til selve diagrammet.<br />

Fly<strong>Simulator</strong> starter en XMLParser op, som instansiere KameraVinkler og Scene objekterne.<br />

For hvert Kamera objekt, som KameraVinkler indeholder, vil den kalde det Kameras<br />

klik metode. Kamera vil for hver pixel i sit billed, spørge Scene om farven i dette punkt.<br />

Sekvensdiagram for Scene I bilag A.4 kan man se et sekvensdiagram over en kørsel med<br />

Scene. Scene undersøger, om vektoren, som der bliver spurgt om, rammer noget, hvis ikke,<br />

returnere Scene. Hvis en punkt rammes, undersøger Scene om solen’s str˚aler ogs˚a rammer<br />

dette punkt som det første. Hvis de ikke gør, skygger en figur for solen, og Scene returnere.<br />

Hvis solen falder p˚a punktet, skal farven i punktet udregnes. Scene spørger den p˚agældende<br />

Figur om farven. I henhold til opgaveformuleringen, henter Figur sin normalvektor i dette<br />

plan, og udregner og returnerer farven.<br />

3.3 Analyse og diskussion af det objektorienterede design<br />

Dette afsnit vil argumentere for, og diskutere det objektorienterede design, som det blev<br />

fremlagt i forrige afsnit.<br />

3.3.1 Generel struktur, Model-View-Controller<br />

Tager man udgangspunkt i et tænkt eksempel for en programkørsel, vil der kunne tydes<br />

tre forskellige dele af processen. En indlæsende del, hvor inddata indføres i systemet, og en<br />

beregnende del, hvor selve str˚alesporingen foreg˚ar, og til sidst en afbildende del hvor et billed<br />

præsenteres. Ud af dette ses der, at design mønstret Model-View-Controller med fordel kan<br />

implementeres.<br />

Vi vil i det følgende, gennemg˚a hver del af dette design mønster, som det er implementeret i<br />

vores design. Til sidst forklarer vi, hvorledes dette design opfylder, flere af de ønsker vi stillede<br />

i foranalysen til det objektorieterede design.<br />

Kamera<br />

Figur 3: MVC modellens centrale elementer<br />

XMLParser<br />

Scene<br />

12<br />

Extern inddata<br />

Præsentation<br />

Model/domæne


3.3.2 Model<br />

Modellen er helt klart det centrale i programmet. Modellen er den del af vores system, som<br />

implementere problemdomænets egenskaber og metoder. I klasser, er der her tale om Scene,<br />

Figur, og de forskellige klasser som nedarver fra figur. Ud over selve de klasser, som omhandler<br />

repræsentation af elementer i Scene, findes der to hjælpeklasser, Vektor og Punkt, som skal<br />

bruges til at lette arbejdet i problemdomænet, ved at have ansvar for mere generelle metoder<br />

ang˚aende vektorudregning.<br />

Data Modellens metoder, og hvorledes data internt i modellen kan tilg˚as, afgører hvilke<br />

slags views som er mulige at præsentere af modellen. Scene har kun en public metode, nemlig<br />

nuance. Det er tydeligt, at hvis man betrageter str˚alesporing som systemets domæne,<br />

begrænser man naturligvis mulige views. Men givet <strong>opgaven</strong>s formulering<br />

De faciliteter, som er nævnt i afsnit 4, angiver en minimal løsning. Det er denne<br />

minimale løsning som skal konstrueres.<br />

virker det som helt rimeligt at begrænse modellens tilgængelige data, p˚a denne m˚ade.<br />

3.3.3 View<br />

View delen af designet, er klassen Kamera. James Rumbaugh [3] opsummere meget præcist,<br />

hvilket forhold view har til modellen<br />

... views must know about [model] data (but not [model] operations).<br />

Kamera klassen tager et billed af en Scene, som den modtager som parameter i sin metode<br />

klik. For en nærmere beskrivelse af hvordan billedet tages (str˚alespores), henvises til<br />

programmeringsovervejelserne.<br />

Præsentation Viewet st˚ar for at visualiserere, eller p˚a anden m˚ade præsentere de data som<br />

eksistere i den p˚agælgende model, hvortil viewet er tilknyttet. I vores designstruktur, eksistere<br />

denne relation kun i den tid, det tager for billedet at tage sit billede. Dette forsimpler Kamera<br />

klassen væsentligt, idet der ikke er nogen dynamiske forhold, at tage højde for. Kamera er<br />

ogs˚a den klasse, som sørger for at uddata udskrives, omend selve udskrivningen sker i Kanvas<br />

klassen.<br />

3.3.4 Controller<br />

Controller er den del af systemet, som er meget implementations specifik. Netop fordi Controlleren<br />

h˚andterer inddata, f.eks. i form af en grafisk brugerflade, eller som til denne opgave,<br />

i form af parsning af XML inddata.<br />

Controller manifesteres i vores design, som klassen XMLParser.<br />

Da Controlleren er implementationsafhænging, og ud over dette er meget specifik for<br />

processen, er det en god ide, at lægge denne i toppen af et associationsdiagram, s˚aledes at<br />

XMLParser afhænger af alt, men intet afhænger af XMLParser.<br />

Denne konstruktion vil tillade at man let udskifter hvordan man bruger et program,<br />

uden at det ville p˚avirke programmets domæneomr˚ade. Man kunne fx. ogs˚a forestille sig<br />

at Controlleren var en grafisk brugerflade, hvor brugeren kunne specificere sin Scene som<br />

brugeren ønskede.<br />

13


3.3.5 Konklusion p˚a objektorienteret design<br />

Det er helt klart at designet af systemet, er lykkedes godt. Problemdomænet er isoleret grundigt<br />

i Scene, præsentation af data i Scene afbildes i klassen Kamera, mens det understøttende<br />

kode, XMLParser og anden ind- og uddata, ligges øverst.<br />

I vores design virker det logisk, at Scene formulere lyset (farven, set fra et punkt), mens<br />

Kamera blot er passiv, og bare kigger i en retning, og optager det den ser. Kamera har ingen<br />

indflydelse p˚a hvorledes billedet ser ud, præcis som i virkelig situation.<br />

Det er dog vigtigt at sige, at dette kun er tilfældet, fordi vores Scene kun deler en type<br />

af data. Hvis den tillod mere, kunne man sagtens forestille sig mere avancerede views.<br />

3.3.6 Cyklisk process<br />

Som en konsekvens af det objektorienterede design, kan programmet tydeligvis opbygges og<br />

videreudvikles i en cyklisk process. Ved at begrænse os til at Scene deler en slags data,<br />

forsimples meget af designet, og konstruktion af visse klasser gøres lettere (og/eller mindre).<br />

Yderligere er det nemt at forestille sig, at man i første omgang definerer de basale klasser,<br />

fx. Scene, og bygger der p˚a. Kamera derefter, og efterh˚anden tilføjer implementationer af figur<br />

typer.<br />

3.3.7 Det objektorienteret design af domænet<br />

Det er ogs˚a interssant at kigge p˚a hvorledes objekterne i selve programmets problem domæne<br />

forholder sig til hinanden.<br />

Figur Figur er den superklasse, som alle andre repræsentationer af elementer i domænet<br />

nedarver fra. Ideen med at Figur er superklassen er, at den definere alle de metoder, som er<br />

nødvendige, for at lave de nødvendige udregninger. Som f.eks. skæringspunkt, farve (skygge),<br />

osv. Det er de individuelle klasser (Kugle, Plan, Trekant), som st˚ar for implementationen af<br />

den specifikke rumgeometriske udregning for den type figure.<br />

Scene Scene er der hvor ansvaret for at styre hele den process, der ligger i at skulle lave<br />

str˚alesporing. Den st˚ar ikke for selve genereringen af de korrekte data, men skal videresende,<br />

eller udvælge de rigtige data.<br />

Ved at ligge generering af data i klassen Figur kan Scene sørge for at modtage de korrekte<br />

data, uden at skulle kende noget til de enkelte figureres specifikke implementation.<br />

Vektor og Punkt Ideen med at indfører Vektor og Punkt klasser til repræsentation af<br />

vektor og punkt information er fordi, de essentielt set internt kun opbevarer tre tal (i et<br />

tre dimensionelt rum). Men istedet for at have disse tal i systemet som et tal array, hvor<br />

betydningen kan være flertydig, alt efter sted og formel. S˚a kan der ikke være tvivl om hvad<br />

inddata er, n˚ar der kommer en Vektor ind, modsat et Punkt.<br />

3.3.8 Figur design<br />

Et sidste aspekt af designet som vi mener er værd at kigge p˚a, er den m˚ade hvormed figurene<br />

forholder sig internt mellem hinanden, og agreggere eller nedarver funktionalitet. Dette ses<br />

iøvrigt tydeligt i bilag A.2.<br />

14


Figur Klassen Figur er superklassen, som alle repræsentationer af elementer i domænet,<br />

nedarver fra. Figur er en abstrakt klasse, som ikke kan instansieres. For at Scene vil arbejde<br />

med en repræsentation af en type element i domænet, skal denne nedarve fra Figur (med<br />

undtagelse af Punkt og Vektor).<br />

Figur definere to abstrakte metoder findNormalvektor og skaeringspunkt. Klassen<br />

definere ogs˚a en sidste konkret metode, nuance. Denne opdeling er kommet, fordi n˚ar først<br />

en klasse har fundet det ramte punkt (hvis et s˚adant findes), og har udregnet normalvektoren<br />

for dette punkt, s˚a er m˚aden hvor p˚a farven for dette punkt udregnes fælles for alle figurer.<br />

Plan Plan klassen repræsentere et uendeligt plan i modellen.<br />

Trekant Trekant klassen konstruere internt et plan, nemlig det plan, som trekantens tre<br />

hjørner udspænder. Ideen med at aggregere en Plan i Trekant er at lave en hurtig udregning,<br />

om en synslinie, overhovedet skære det samme plan, som trekanten ligger i.<br />

Hvis en synslinie skærer det samme plan, som trekanten ligger i, s˚a kan man g˚a videre, og<br />

se om det skæringspunkt, ligger inde i trekanten.<br />

Mesh Mesh klassen, repræsentere et net af trekanter. Og dette er den faktiske repræsentation<br />

af figuren, som internt vil have et array af klassen Trekant. I samme stil som Scene skal Mesh<br />

blot holde styr p˚a sine Trekant medlemmer, og sende de rigtige data, tilbage til Scene.<br />

Kugle Kugle klassen er lidt selvst˚aende, da den ikke deler funktionalitet med nogen anden<br />

klassen, den nedarver blot fra Figur.<br />

4 Programmeringsovervejelser<br />

Dette afsnit vil diskutere, hvorledes implementationen af det objektorienterede design er mulig<br />

i Java, og hvordan kritiske punkter omkring dette behandles. Slutteligt vil køretider for<br />

programmet blive diskuteret.<br />

4.1 Programstruktur<br />

Da vores objektorienterede design er specificeret helt ned til detaljen af, hvilke klasser der<br />

skal kunne hvad, og hvilken m˚ade metodekaldene sker p˚a kryds og tværs af klasserne, s˚a<br />

vil denne diskussion forholde sig til, hvorvidt det er muligt at sammensætte programmet p˚a<br />

denne m˚ade.<br />

Overordnet Designet er ret ligetil at implementere, i Java. Der er intet ønske om at anvende<br />

funktionalitet som ikke eksistere i Java, og Java vil ikke lægge nogen begrænsninger p˚a idéerne<br />

bag designet.<br />

Det funktionalitetsgenbrug som er ønsket i designet er fuldt ud muligt at implementere,<br />

og ved steder - s˚asom at skabe nye figure - kan den ønskede fleksibilitet i designet faciliteres.<br />

15


Datatyper Ser vi først p˚a de datastrukturer som ønskes anvendt, s˚a finder vi at de eneste<br />

to egentlige datatyper som findes er Vektor og Punkt. Ved datatyper i denne forbindelse<br />

forst˚as ”traditionelle”datatyper, ligesom f.eks. en talliste, som anvendes mellem programmets<br />

klasser til overlevering af information, og ikke som funktionel programkode.<br />

Efter programstart er den eneste nødvendige information, som klasserne imellem har brug<br />

for at udveksle, er punkter og vektorer, ud over de sædvanlige Java definerede primitiver og<br />

datatyper.<br />

Databehandling Ser man p˚a det samspil som skal findes mellem klasserne, er et kritisk<br />

punkt samspillet mellem Kamera og Scene, hvori det betragtes Scenes kald til dens objekter<br />

af klassen Figur.<br />

I Scene beregnes skæringspunkterne i selve figurerne, hvilket gør at ansvaret, med at finde<br />

ud af hvilken formel der skal bruges til en specifik figur, bliver overladt til figuren.<br />

Ligeledes overlades udregningen af normalvektoren til figurerne, hvilket ogs˚a gør at ansvaret<br />

er overdraget til figurerne, som ogs˚a er de eneste som kan udføre udregningen.<br />

Med disse to metoder defineret abstrakte, og dermed overladt til de klasser om nedarver<br />

fra Figur, bliver den enkelte figur genereliseret og Scene kan h˚andtere dem ens, ligegyldigt<br />

hvilken klasse der har nedarvet fra Figur.<br />

Overordnet kunne man ogs˚a stille spørgsm˚al, om hvorvidt vektorregningen er p˚alidelig<br />

til udregninger imellem klasserne i praksis. Det eneste problem som kan opst˚a ved dette -<br />

bortset fra generelle systemfejl som overløb - er ved sammenligning af punkter. Analysen er<br />

dog opmærksom p˚a dette.<br />

4.2 Programkørsel<br />

Her sker en gennemgang af hovedalgoritmen i programmet, med belysning af systemorienterede<br />

løsninger p˚a de problemer, som blev behandlet i analysen.<br />

Hovedalgoritmen er som følger:<br />

• For hvert Kamera i Kameravinklers Kamera[] gøres følgende:<br />

– For hver Vektor i Kameras Vektor[][] udregnes der hvilken nuance denne Vektor<br />

skal give i billedet.<br />

1. Beregn skæringspunkter mellem den linje udspændt af hver Vektor og oeje,<br />

og s˚a alle figure i Scenes Figur[], og opbevare den figur og det skæringspunkt<br />

som er tættest p˚a øjet. Ramte linjen overhovedet ingen figure returneres farven<br />

sort, ellers næste trin.<br />

2. Beregn skæringspunkter mellem den linje udspændt af solen og skæringspunktet<br />

fra før, og alle figurer i Scenes Figur[]. Undersøg om det første skæringspunkt<br />

p˚a linjen er det samme som det punkt der blev fundet i den tidligere<br />

beregning. Er det ikke det samme punkt returneres farven sort, ellers næste<br />

trin.<br />

3. Find nuancen for det skæringspunkt p˚a den figur som blev ramt i første trin.<br />

Placer denne nuance i billedet p˚a samme koordinat som vektoren har i Kameras<br />

Vektor[][].<br />

– Alle de fundne nuancer anbringes i Kanvas og udskrives til ppm format.<br />

16


Fælles for alle af disse skridt er, at der for hver af dem er tilknyttet, et eller flere af de<br />

problemer, som blev belyst i den problemorienterede analyse.<br />

1. skridt N˚ar skæringspunkterne udregnes, skal vores valg om, at der ikke m˚a forekomme<br />

noget mellem øjet og filmen tages i betragtning.<br />

For hver af de Vektor objekter som findes i Kameras Vektor[][] og oeje udregnes der<br />

hvilken værdi der skal indsættes i parameterfremstillingen for linjen (alts˚a t’s værdi i ligningen<br />

(xs, ys, zs) = (xp, yp, zp) + (xv, yv, zv) · t), for at rammer hvert skæringspunkt p˚a linjen.<br />

Da hver Vektor sammenlagt med oeje giver et punkt i filmen, er det oplagt at bestemme,<br />

om et punkt kan ses af Kamera eller ej, ud fra værdien af t.<br />

Derfor gælder der for udregningen af skæringspunkter, at t’s værdi skal være t > 1, 0. P˚a<br />

denne m˚ade bliver der samtidig sørget for at skæringspunktet ikke ligger ligger før filmen eller<br />

bag øjet. Se figur 4.2.<br />

t < 0<br />

Figur 4: t’s værdier relative til vektorens længde<br />

pilotøje<br />

0


Derfor er det nødvendigt at nedskalere Vektor’en mellem lyskilden og skæringspunktet<br />

fra 1. skridt til længde 1, inden beregningerne fortsættes.<br />

Ud af de t’er som kommer ud af beregningen, vælges det p t som er tættest p˚a 0, hvor<br />

der gælder at t > 1.0. Det skæringspunkt som betragets som først ramt, er det punkt som<br />

resulteres ved indsættelse af det mindste t i parameterfremstillingen.<br />

Sammenligningen mellem de to punkter sker nu ved at fremstille et Vektor objekt med<br />

disse punkter, og vurdere længden af dette.<br />

Vi har valgt at længden 0.000001 betegner om to punkter i modellen er de samme. Denne<br />

værdi er valgt ud fra emperiske undersøgelser med bla. den obligatoriske scene. Værdien er<br />

p˚a ingen m˚ade nogen universel værdi, da den kun vurdere punkterne i forhold til scenen.<br />

Beskriver en bruger alts˚a en scene med meget sm˚a tal, vil denne værdi m˚aske bevirke at<br />

linjerne i billedet bliver uskarpe, da afstandene mellem figurer i rummet, kan være s˚a sm˚a i<br />

forhold til værdien, at de bliver fejlvurderet. Alts˚a at to punkter der burde være forskellige,<br />

bliver vurderet til at være de samme.<br />

Ligeledes kan man forestille sig den omvendte effekt, ved operationer med meget store<br />

talværdier. Alts˚a at et punkt bliver vurderet til at være to forskellige punkter.<br />

En logisk fejl kan ogs˚a ske i dette skridt, i tilfælde af at solen ikke rammer noget punkt<br />

overhovedet. Dette er en klar logisk fejl, da Vektor objektet jo som bekendt er skabt ud fra<br />

et skæringspunkt mellem lyskilde og figur. Der kastes derfor en undtagelse da det anses som<br />

en uoprettelig fejl, der vil give forkert uddata. Undtagelsen kan kun opst˚a ved at en figur er<br />

placeret mindre en afstand 1 fra lyskilden, fordi solens vektor skaleres ned til 1.<br />

3. skridt Ved nuanceberegning var det som sagt vigtigt, at figurens normalvektor peger<br />

imod øjet for at formlen p˚a - [2] side 7 nederst - giver mening. Derfor undersøges, før en<br />

normalvektor udvælges, hvilken vej den skal vende. Det gøres ved at sammenligne længden<br />

p˚a to vektorer, som skabes mellem øjepunktet og normalvektoren set ud fra skæringspunktet,<br />

og en vektor ligeledes skabt bortset fra at normalvektoren er inverteret. Den normalvektor<br />

som returneres er den som indgik i den vektor, hvis længde var kortest. Se figur 4.2.<br />

pilotøje<br />

Figur 5: Udvælgelse af normalvektor<br />

film<br />

18<br />

plan<br />

normalvektor<br />

inverteret normalvektor


4.2.1 Køretid for hovedalgoritmen<br />

En køretid for algoritmen er svær at fastsl˚a præcist. Der er mange faktore som spiller ind,<br />

helt ned til hvordan figurerne er placeret i scenen. F.eks. s˚a vil en scene, hvor alle figurerne er<br />

placeret bag kameraet, have en køretid som er væsentlig hurtigere, end hvis alle figurerne var<br />

placeret foran kameraet s˚a alle deres nuancer skulle udregnes. Antallet af beregning er derfor<br />

svært at fastsl˚a.<br />

En generelisering af køretiden, kunne basere sig p˚a de variabler i programmet som er<br />

faste. Disse variabler er højden og bredden (h og b) som ønskes i uddata, da disse definere<br />

hvor mange pixels der skal udregnes nuancer for. herudover er der antallet af figurer (n), og<br />

slutteligt antallet af billeder/kameravinkler ønsket fra scenen k.<br />

Den hurtigeste køretid som programmet kan opn˚ar er defineret til at være:<br />

<br />

O (h1 · b1) + (h2 · b2) + . . . + (hk · bk) · n<br />

Dette udledes af, at der for hver pixel i hvert billede, skal laves et gennemløb af alle figurer<br />

i scenen. Som det ses s˚a er der kun en beregning for hver figur, og det betyder, at dette er<br />

situationen, hvor ingen figurer i hele billedet, i alle billederne, er blevet ramt.<br />

I værste tilfælde ville køretiden se s˚aledes ud:<br />

<br />

O (h1 · b1) + (h2 · b2) + . . . + (hk · bk)<br />

· n 2<br />

<br />

Til forskel fra den hurtigeste køretid, s˚a indeholder denne et ekstra gennemløb, hvor der for<br />

hvert skæringspunkt udregnes om lyskilden rammer punktet, ved et gennemløb af alle figurer.<br />

5 Brugervejledning<br />

Indlæsning Programmet køres med filen Fly<strong>Simulator</strong>, som valgfrit kan tage kun en XMLfil<br />

som argument. Hvis programmet ikke f˚ar et argument, prøver den at ˚abne en standardfil<br />

ved navn lufthavn2.xml. Et kald af programmet vil se ud s˚aledes:<br />

>java Fly<strong>Simulator</strong> LaGuardia.xml<br />

Argumentfilen skal ligge i samme mappe og den skal være i valid XML format, hvilket uddybes<br />

herunder.<br />

Uddata vil best˚a af et/flere billede(r) i .ppm filformat med samme navn som pilotsyns<br />

id(er) angivet i XML, dette uddybes nedenunder.<br />

Eksempel Nedenfor er et simpelt eksempel. Det indeholder de figurer som programmet kan<br />

tegne:<br />

<br />

<br />

<br />

<br />

<br />

<br />

19


<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

5.1 Anvendelse af tags<br />

Scene Inddata best˚ar først af en s˚akaldt tag, der beskriver hvilken XML-udgave vi bruger<br />

og hvilket tegnsæt. Dernæst kommer -taggen, inden i dette beskrives selve scenen.<br />

Generelt gælder det at XML-tags, der indeholder andre XML-tags, skrives p˚a formen<br />

... evt andre tags...<br />

Tags, der ikke indeholder andre tags, kan skrives som<br />


pilotsyn Denne tag beskriver en øjenposition og retning. I selve -taggen angives<br />

ogs˚a højden og bredden i pixels af det billede der skal udskrives. Der defineres ogs˚a 4 punkter<br />

i . Det er pilotoeje der er øjepunktet, der ses fra. cockpitvindue stedpunkt er<br />

det punkt fra hvilket udspændes. cockpitvindue lodret er den vektor, der svarer til biledets<br />

lodrette retning. cockpitvindue_vandret er den vektor, der svarer til billedets vandrette<br />

retning.<br />

Alle disse punkter defineres vha. -taggen, og gives deres navn vha id-attributten,<br />

dette vil ogs˚a blive navnet p˚a billedet. De tre koordinater skal betragtes som kommatal.<br />

Der kan være arbitrært mange pilotsyn i en scene, og der genereres et billede for hvert<br />

pilotsyn.<br />

sol Denne tag beskriver solens position og farve. Positionen beskrives vha -taggen,<br />

og er givet navnet position. Farven beskrives i -taggen, hvor r-attributten angiver<br />

mængden af rødt, g-attributten mængden af grøn og b-attributten mængden af bl˚a. Alle tre<br />

værdier løber mellem 0 og 255. Disse tal kan kun være heltallige.<br />

kugle Denne tag beskriver en kugle i scenen. Den har et centrum, der angivet som et punkt<br />

med navn centrum. Kuglen har ogs˚a farve, som angivet som beskrevet ovenfor. Kuglen har<br />

ogs˚a en radius. Den angivet med -taggen der har attributten r der giver radius af<br />

kuglen. Radius kan angives i kommatal.<br />

mesh Denne tag beskriver et trekantsgitter. I hvert mesh angives først en punktliste over de<br />

punkter, der indg˚ar i trekantsgitteret. Dernæst kommer en liste af trekanter hvor der i hver<br />

trekant gives tre indeks ind i punktlisten som svarer til de punkter trekanten udspændes af.<br />

Et mesh har ogs˚a farve, som angives som beskrevt ovenfor.<br />

Punktlisten angives som en -tag inden i hvilken punkterne st˚ar defineret fortløbende.<br />

har attributten antal punkter, der angiver hvor mange punkter der er i punktlisten.<br />

Hvert punkt er givet et id, der svarer til hvilket nummer det er i punktlisten.<br />

Trekantslisten angives som en -tag inden i hvilken punkterne st˚ar defineret<br />

fortløbende. har en attribut antal trekanter, der angiver hvor mange punkter<br />

der er i trekantslisten. En har attributter p1, p2 og p3, som angiver de tre<br />

indeks(heltal) i punktlisten, hvor trekantens punkter kan findes.<br />

plan Denne tag beskriver planer. Her menes der alts˚a planer med uendelige stor udstrækning.<br />

En plan er givet ved et stedpunkt(dvs et punkt hvorfra planen udspændes) og to retningsvektorer,<br />

som udspænder planen. Planen har ligesom de andre figurer en farve.<br />

6 Programbeskrivelse<br />

Programmet er skrevet til at blive oversat med Java version 1.4.0, og blive afviklet med samme<br />

virtual machine.<br />

Langt de fleste dele af programmet er nogenlunde simple, og indlysende. Hvor passende,<br />

er der kommenteret. Vi henviser yderligere til de forskellige UML diagrammer i bilaget, for<br />

en forst˚aelse af programstrukturen.<br />

Idet følgende vil der komme en kort beskrivelse af de dele af programmet, som kan drage<br />

nytte af en forklaring.<br />

21


6.1 Kamera<br />

Kamera klassen opbygger internt et gitter i attributten gitter. Her følger en forklaring af<br />

hvordan dette gitter opfyldes med Vektor objekter. Gitteret fyldes, fra toppen, venstre mod<br />

højre. P˚a figur 6 kan man se et eksempel p˚a hvorledes vektorene dannes. Læg dog mærke til<br />

at i vores tilfælde peger l op, og v mod højre (i forhold til øjet), dette behøver naturligvis<br />

ikke være tilfældet, men det letter forst˚aelsen.<br />

Figur 6: En opstilling i Kamera klassen, for et billed med opløsning p˚a 6x6 pixels<br />

pilotøje<br />

step_l<br />

l = cockpitvindue_lodret<br />

s = cockpitvindue_stedpunkt<br />

step_v<br />

b = 6<br />

v = cockpitvindue_vandret<br />

Den primære ide er, først at beskrive gitterpunktet som et Punkt objekt. Herefter bruges<br />

pilotoeje som punkt, og en vektor beskrives mellem gitterpunktet, og pilotøjet. Det er denne<br />

vektor, som der skal str˚alespores ud af, og den gemmes i gitter arrayet.<br />

step v og step l Disse to vektorer, beskriver det hop, som gitteret skal lave, hver gang<br />

man ændre række eller søjle. Alle punkter i gitteret kan beskrives ud fra en kombination af<br />

n ∗ step l + m ∗ step v. Da man kun skal lave n − 1 hop for at være n forskellige steder, derfor<br />

subtraheres h og b begge med 1, n˚ar step l og step v skal udregnes.<br />

For-løkken i Kamera klassen, gør følgende. Først bygges den lodrette vektor op, med koden<br />

Vektor.skaler(step_l,h-(i+1)), dette tager step l, h-(i+1) gange. i er iteration nedover<br />

rækkerne. Ved første gennemløb vil dette da give den fulde højde (l). Til denne lodrette<br />

vektor ligges Vektor.skaler(step_v,i2), hvilket giver den vandrette vektor, i2 gange. i2<br />

er iteration henover kollonnerne. Dette giver da en vektor, som g˚ar fra s til det gitter punkt<br />

vi er n˚aet til. Vi laver s om til en vektor, og ligger den sammen med vektoren som gik fra s<br />

til gitterpunktet. Denne vektor laves da om til et punkt.<br />

22<br />

h = 6


Herefter er det nemt at lave en vektor, som g˚ar fra p (pilotøje) til gitterpunktet med linien<br />

gitter[i][i2] = Vektor.lavVektor(p,gitterPunkt).<br />

Hvis en længde af billedet er en pixel, da sættes den p˚agældende step vektor ogs˚a til nul.<br />

Dette betyder, at hvis man beder om et billed 1 højt, s˚a kommer vektorerne til at g˚a gennem<br />

punkter, p˚a ligger ud af den akse, som v udspænder (se evt figur 6).<br />

7 Afprøvning<br />

Tankegangen bag denne afprøvningen er at dokumentere at vores program implementere en<br />

simpel flysimulator vha. en str˚alesporer, og finde eventuelle fejl i vores program. Afprøvningen<br />

er ekstern, alts˚a skal programmet betragtes som en ”blackbox”, forst˚aet p˚a den m˚ade, at vi kun<br />

kan give inddata og analysere uddata, men ikke se hvordan programmet opfører sig internt.<br />

Vi vil følgende liste alle krav til programmet, inddelt i ækvivalensklasser. Ækvivalensklasserne<br />

deles op i emner. Dvs. en ækvivalensklasse har referencen eks. 2.b eller 1.a.<br />

1. Krav fra opgaveformuleringen[2] og den problemorienterede analyse 2.<br />

(a) Indlæse en fil i XML format.<br />

(b) Opbygge scene udfra XML fil.<br />

(c) Have kugler, trekanter og planer som grundformer<br />

(d) Generere et farvebillede for hver flyposition.<br />

(e) Lade lysstr˚ale komme fra en punktformig lyskilde.<br />

(f) Gemme de genererede billeder i et filsystem.<br />

(g) Genererer sekvensen af billeder der er beskrevet i bilag C i opgaveformuleringen.<br />

2. Programmet skal vha teorien fra opgaveformuleringens [2] returnere de rigtige farve i<br />

billedet.<br />

(a) Programmet skal returnere den rigtige nuance for et givet punkt. Programmet skal<br />

give samme resultat som de matematiske formler fra opgaveformuleringen[2]<br />

3. Krav til opstilling i 3 dimensioner.<br />

(a) Hvis en figur er placeret bagved øjet, skal den ikke med i billedet, men solen skal<br />

tage den med i beregning af skygger.<br />

(b) Hvis en figur omgiver øjepunktet, men ikke n˚ar ud forbi filmen, skal den ikke med<br />

i billedet, men solen skal tage den med i beregning af skygger.<br />

(c) Hvis en figur skærer filmen, skal det af figuren som befinder sig mellem øjet og<br />

filmen ikke med i billedet, men solen skal stadig tage højde for det omr˚ade.<br />

(d) Hvis en figur omslutter b˚ade øjet og filmen, skal det synlige omr˚ade af figuren kun<br />

med hvis solen skinner p˚a det.<br />

(e) Programmet skal kunne h˚andtere en scene uden nogle figurer.<br />

(f) Programmet skal kunne h˚andtere at et plan ligger parallelt med synsretningen.<br />

(g) Hvis solen skinner p˚a bagsiden af en figur, skal figuren være sort.<br />

(h) Programmet skal kunne h˚andtere ekstreme talværdier, s˚asom 10 ∗ 10 16 .<br />

23


(i) En sol skal kunne være inden i en figur, som skærer i filmen.<br />

4. Krav til XML (vil blive uddybet i afsnit 7.4)<br />

(a) Punkt<br />

(b) Farve<br />

(c) Placering af tags<br />

(d) Rod tag<br />

(e) Pilotsyn<br />

(f) Sol<br />

(g) Kugle<br />

(h) Plan<br />

(i) Trekant<br />

(j) Mesh<br />

Herunder vil de ovenst˚aende emner og deres individuelle ækvivalensklasser blive uddybet<br />

og afprøvet.<br />

7.1 Obligatoriske billeder<br />

Da kravene i dette afsnit ikke er særlig specifikke vil vi betragte dem som opfyldt hvis programmet<br />

kan udføre nedenst˚aende. Disse krav ligger ogs˚a til grund for at vi ikke vil afprøve<br />

grænsetilfælde i dette afsnit.<br />

Krav<br />

1. Indlæse en fil i XML format.<br />

2. Opbygge scene udfra XML fil.<br />

3. Have kugler, trekanter og planer som grundformer<br />

4. Generere et farvebillede for hver flyposition.<br />

5. Lade lysstr˚ale komme fra en punktformig lyskilde.<br />

6. Gemme de genererede billeder i et filsystem.<br />

7. Generere sekvensen af billeder der er beskrevet i bilag C i opgaveformuleringen.<br />

Inddata Som inddata vælges den obligatoriske XML fil.<br />

Uddata Der forventes 3 billeder nøjagtig som XML beskriver dem. Se figur 7, 8 og 9<br />

Resultat Kravene er opfyldt, programmet genererer billederne nøjagtig som de skal.<br />

24


7.2 Matematisk udregning af nuance<br />

Krav Programmet skal udregne nuancen korrekt per den matematiske model. Da udregningen<br />

er ens for alle figurer og de tre forskellige grundfarver er en afprøvning nok til at afgøre<br />

om kravet er opfyldt for alle figurer og farver. Vi vil dog opstille 4 forsøg for at n˚a nogle<br />

grænsetilfælde i vinklen mellem solen og normalvektoren. Ens for alle 4 afprøvninger, benyttes<br />

der et plan med farven (255,0,0) alts˚a helt rød. Udregningerne benytter denne formel:<br />

<br />

solx∗ <br />

SolRGB ∗ fk ∗<br />

nuance =<br />

Nx+ soly∗ Ny+ solz∗ Nz<br />

√ √<br />

( solx) 2 +( soly) 2 +( solz) 2∗ ( Nx) 2 +( Ny) 2 +( Nz) 2<br />

<br />

∗ F igurRGB<br />

255<br />

M˚aden vi har testet p˚a er at opstille en XML scene hvor billedet bliver nøjagtig 1x1 pixel<br />

og hvor vi har kunne kontrollere vinklerne præcist. Programmets udregnede nuance er bestemt<br />

gennem en farveanalyse(tegneprogram) af det genererede billede, vi har ikke inkluderet<br />

uddata(1x1 pixel billederne) da dette ville være nytteløst.<br />

Vinkel 0<br />

• Inddata Vinklen mellem solen og normalvektoren vil her være 0 grader. Inddata kan<br />

ses i bilag D.2<br />

• Forventet Uddata<br />

<br />

255 ∗ 1.0<br />

Forventet farve (255,0,0)<br />

• √<br />

Vinkel 45<br />

<br />

√ 0∗0+0∗0+−1∗−1 √<br />

02 +02 +−12∗ 02 +02 +−12 255<br />

∗ 255 = 255<br />

• Inddata Vinklen mellem solen og normalvektoren vil her være 45 grader. Inddata kan<br />

ses i bilag D.2<br />

• Forventet Uddata<br />

<br />

255 ∗ 1.0<br />

Forventet farve (180,0,0)<br />

• √<br />

Vinkel 90<br />

<br />

√ 0∗0+0∗1+−1∗−1 √<br />

02 +02 +−12∗ 02 +12 +−12 255<br />

∗ 255 = 180<br />

• Inddata Vinklen mellem solen og normalvektoren vil her være 90 grader.<br />

• Forventet Uddata Dette vil ikke være muligt da denne scene kræver at solvektoren<br />

ligger parallel med planet og de vil derfor ikke skærer hinanden.<br />

25


Vinkel 180<br />

• Inddata Vinklen mellem solen og normalvektoren vil her være 180 grader.<br />

• Forventet Uddata Dette vil ikke være muligt i virkeligheden.<br />

7.3 Krav til opstilling i 3 dimensioner<br />

Dette afsnit handler om kravene til hvordan figurer opfører sig n˚ar vi flytter rundt p˚a dem<br />

i rummet. Det er umuligt at teste alle tilfælde da der er uendelig mange, og vi har allerede<br />

vist et udsnit af de trivielle tilfælde i afprøvningen af den obligatoriske scene. Vi vil derfor<br />

i dette afsnit prøve at ramme nogle grænser som ikke er berørt i den obligatoriske scene, og<br />

som vi har opstillet krav til vores program skulle kunne h˚andtere. Disse grænser handler især<br />

om hvad der sker n˚ar figurer kommer tættere p˚a filmen og øjet.<br />

Vores uddata kan være problematisk at tolke, da det best˚ar af en 3-dimensionel scene som<br />

konverteres til 2 dimensionel gr˚atonegengivelse, for at kunne printes. Derfor vil vi teste en<br />

ækvivalensklasser af gangen, da uddata meget hurtigt kan blive uoverskueligt. Vi vil beskrive<br />

kravet som testes, angive de karakteristiske egenskaber ved inddata og henvise til hvor de<br />

kan findes, angive det forventede uddata og hvor det kan findes, og sidst angive om kravet er<br />

opfyldt. Inddata er i XML format og er inkluderet i bilag D. Uddata er de XML beskrevede<br />

scener i form af gr˚atonebilleder, som ogs˚a er inkluderet i bilag D. Vi har valgt at beskrive<br />

disse afprøvninger i form af afsnit fremfor skemaer, da der medfølger en del forklarende tekst,<br />

som ikke ville være hensigtsmæssig at placere i skemaer.<br />

Test af ækvivalensklasse 3a<br />

• Krav Hvis en figur er placeret bagved øjet, skal den ikke med i billedet, men solen skal<br />

tage den med i beregning af skygger.<br />

• Inddata En kugle der ligger bagved øjet og en kugle der ligger foran øjet, og et hvidt<br />

plan. Inddata se bilag D.3.1.<br />

• Forventet Uddata En skygge fra kuglen der ligger bagved øjet p˚a planet og p˚a en del<br />

af kuglen der ligger foran øjet. Se figur 10<br />

• Resultat Man kan se p˚a figur D.3.1 at kravet om at en kugle bag øjet skal kunne give<br />

skygge men ikke selv være med p˚a billedet.<br />

Test af ækvivalensklasse 3b<br />

• Krav Hvis en figur omgiver øjepunktet, men ikke n˚ar ud forbi filmen, skal den ikke med<br />

i billedet, men solen skal tage den med i beregning af skygger.<br />

• Inddata En kugle(1) rundt om øjet som ikke n˚ar ud til filmen, og en kugle(2) foran<br />

filmen. Inddata se bilag D.3.2.<br />

26


• Forventet Uddata En skygge af kulge(1) p˚a planet. Kugle(2) skal være synlig med<br />

skygge p˚a planet. Se figur 11<br />

• Resultat Kravet er opfyldt, kuglen rundt om øjet er ikke med p˚a billedet, men afgiver<br />

skygge.<br />

Test af ækvivalensklasse 3c<br />

• Krav Hvis en figur skærer filmen skal det af figuren som befinder sig mellem øjet og<br />

filmen ikke med i billedet, men solen skal stadig tage højde for det omr˚ade.<br />

• Inddata Kugle der skærer filmen med mindre en halvdelen bag. Inddata se bilag D.3.3.<br />

• Forventet Uddata Kugle skal have et rundt sort omr˚ade, det skal være sort fordi solen<br />

ikke kan skinne ind i kuglen da den rammer kuglen p˚a den del der er bag filmen. Se<br />

bilag 12<br />

• Resultat Kravet er opfyldt. Solen kan ikke skinne ind i kuglen ergo bliver det inde i<br />

kuglen sort.<br />

Test af ækvivalensklasse 3d<br />

• Krav Hvis en figur omslutter b˚ade øjet og filmen, skal det synlige omr˚ade af figuren<br />

med hvis solen skinner p˚a det.<br />

• Inddata En kugle som omslutter øje, film og sol. En kugle foran filmen inden i den<br />

omsluttende kugle. Inddata se bilag D.3.4.<br />

• Forventet Uddata Skal kunne se indersiden af den store kugle. Den lille kugle skal ses<br />

og skal kaste skygge p˚a indersiden af den store kugle. Se figur 13<br />

• Resultat Kravet er opfyldt. Man kan se indersiden af kuglen som omslutter øjet og<br />

filmen, da solen er inden i figuren.<br />

Test af ækvivalensklasse 3e<br />

• Krav Programmet skal kunne h˚andtere en scene uden nogle figurer.<br />

• Inddata En scene uden nogle figurer. Inddata se bilag D.3.5.<br />

• Forventet Uddata Et helt sort billede. Se figur 14<br />

• Resultat Kravet er opfyldt, billedet bliver helt sort.<br />

Test af ækvivalensklasse 3f<br />

• Krav Programmet skal kunne h˚andtere, at et plan ligger parallelt med synsretningen.<br />

• Inddata 3 planer sat op som et hjørne af et rum. En kugle til at give noget perspektiv.<br />

Og et plan som ligger parallelt med synretningen. Inddata se bilag D.3.6.<br />

• Forventet Uddata Hjørnet af et rum, med en kugle. Men uden spor af planet som<br />

ligger parallelt med synsretningen. Se figur 15<br />

• Resultat Kravet er opfyldt, der er intet spor af det parallele plan.<br />

27


Test af ækvivalensklasse 3g<br />

• Krav Hvis solen skinner p˚a bagsiden af en figur, i forhold til øjet, skal figuren være<br />

sort.<br />

• Inddata 2 kugler foran filmen, den ene næsten bagved den anden i forhold til øjet, og<br />

en sol mellem kuglerne. Inddata se bilag D.3.7.<br />

• Forventet Uddata Kuglen længst væk skal være synlig og skygge p˚a planet, kuglen<br />

tættest p˚a skal være sort da solen ikke skinner p˚a den. Se figur 16<br />

• Resultat Kravet er opfyldt, kuglen tættest p˚a er sort da solen skinner p˚a bagsiden.<br />

Test af ækvivalensklasse 3h<br />

• Krav Programmet skal kunne h˚andtere ekstreme talværdier, defineret ved starten af<br />

afprøvningen, som input værdier.<br />

• Inddata Et plan som er angivet med en ekstrem talværdi. Og en kugle til at give<br />

perspektiv. Inddata se bilag D.3.8.<br />

• Forventet Uddata En kugle der skygger p˚a et plan bagved. Se figur 17<br />

• Resultat Kravet er opfyldt, programmet kan godt h˚andtere store tal. Denne afprøvning<br />

har dog afsløret at udregningerne i programmet kan fejle, da det ses at planet er flimret.<br />

Test af ækvivalensklasse 3i<br />

• Krav En sol skal kunne være inden i en figur, som skærer i filmen.<br />

• Inddata En stor kugle som skærer filmen med to sm˚a kugler inden i, og solen ligger i<br />

den store cirkels centrum. Inddata se bilag D.3.9.<br />

• Forventet Uddata Den skærende kugle skal have samme farve overalt indeni. De to<br />

sm˚a kugler skal give skygge p˚a indersiden af den store kugle. Se figur 18<br />

• Resultat Kravet er opfyldt.<br />

7.4 XML krav<br />

Vi vil her opstille nogle ækvivalensklasser for de krav vi har sat til XML’en. Vores program<br />

skal efter hensigten stoppe og give en fejlmeddelelse hvis XML ikke er syntaktisk korrekt.<br />

Beskeden skal s˚a vidt mulig angive hvilken type tag fejlen er fundet i, men er desværre ikke<br />

istand til at angive hvor det tag befinder sig. Denne opbygning gør det ikke muligt at teste<br />

for mere end et krav ad gangen. Vi vil i disse test forsøge at give programmet forkert inddata<br />

f˚ar at se om det giver de passende fejlbeskeder. Vi vil tage den obligatoriske scene som bevis<br />

for at vores program kan læse syntaktisk korrekt XML.<br />

Til afprøvningerne vil vi bruge en template til inddata, dette skyldes at inddata vil ligne<br />

denne template, med undtagelse i de linier hvor vi indsætter fejldata. Forskellen fra templaten<br />

vil blive listet med linienummer i de følgende testafsnit under inddata. Der vil følge<br />

en beskrivelse af egenskaberne ved inddata. Uddata vil best˚a af korte fejlbeskeder, disse vil<br />

28


ogs˚a blive listet i afsnittet sammen med hvad vi forventede af uddata. Der vil være et √ hvis<br />

afprøvningen forløb som forventet, hvis ikke vil det blive uddybet. N˚ar et tag er blevet testet,<br />

vil det ikke blive testet igen, hvis det g˚ar igen under et andet tag.<br />

Templaten er s˚aledes:<br />

l1 <br />

l2 <br />

l3 <br />

l4 <br />

l5 <br />

l6 <br />

l7 <br />

l8 <br />

l9 <br />

l10 <br />

l11 <br />

l12 <br />

l13 <br />

l14 <br />

l15 <br />

l16 <br />

l17 <br />

l18 <br />

l19 <br />

l20 <br />

l21 <br />

l22 <br />

l23 <br />

l24 <br />

l25 <br />

l26 <br />

l27 <br />

l28 <br />

l29 <br />

l30 <br />

l31 <br />

l32 <br />

l33 <br />

l34 <br />

l35 <br />

l36 <br />

l37 <br />

Følgende test er stillet op denne m˚ade:<br />

Krav specifikation<br />

Karakteristiske egenskaber ved inddata.<br />

29


Specifikke inddata, startende med det linienummer hvor data passer ind i templaten.<br />

Forventet uddata og resultat<br />

Uddata<br />

Linien ”krav”kan godt indeholde flere krav og test af disse vil følge under med et lille mellemrum.<br />

Krav: Punkt skal angives med x,y,z attributter med værdier angivet i tal (n/.n/n.n/n.)<br />

Der mangler en attribut<br />

l16 <br />

Forventer en fejlbesked om manglende attribut. √<br />

XML fejl: ’s x/y/z attributter var ikke i korrekt format<br />

X’s attribut bliver angivet i forkert format<br />

l25 <br />

Forventer en fejlbesked om forkert format √<br />

XML fejl: ’s x/y/z attributter var ikke i korrekt format<br />

Krav: Farve skal angives med attributerne r,g,b og de skal angives i heltalsformat med værdier<br />

0-255<br />

Farves attribut r er kaldt t<br />

l10 <br />

Forventer fejlbesked om farves attributter ikke er i rigtig format √<br />

XML fejl: ’s r/g/b attributter var ikke i korrekt format<br />

Farves r attribut er sat til værdi uden for grænsen<br />

l10 <br />

Forventer en fejlbesked om værdi uden for grænse √<br />

XML fejl: ’s r/g/b attributter var uden for 0-255<br />

Krav: Rod tagget skal hedde scene<br />

Vi har omdøbt scene tagget<br />

l2 ¡rodsteward¿<br />

l137 ¡/rodsteward¿<br />

Forventer en fejlbesked om forkert XML format √<br />

XML fejl: Rod-element skal være af type <br />

30


Krav: Der skal være mindst et pilotsyn tag<br />

Vi har fjernet pilotsyn tagget<br />

l3<br />

l4<br />

l5<br />

l6<br />

l7<br />

Vi forventer en fejlbesked om at der mangler et pilotsyn tag √<br />

XML fejl: Der kræves mindst et pilotsyn.<br />

Krav: Der m˚a kun være en sol i top niveau<br />

Der er placeret en sol mere i top niveau<br />

l38 <br />

l39 <br />

l40 <br />

l41 <br />

Der forventes en fejlbesked om der er for mange sole √<br />

XML fejl: For mange <br />

Krav: Programmet skal kunne acceptere 3 slags figurer. Kugle, mesh og plan.<br />

Templaten indeholder alle 3 slags figurer. S˚a der er ikke nogle ændringer ved inddata Vi<br />

forventer at programmet forløber uden problemer √<br />

% af figur.ppm faerdig<br />

0%-----------------------------------50%-----------------------------------100%<br />

###############################################################################<br />

Krav: Kugle skal have centrum (i punktformat), radius tag (med r attribut, som skal angives<br />

positivt) og farve tag (farveformat)<br />

Kugle tag mangler centrum<br />

l35<br />

Forventer fejlbesked om at der er for f˚a/mange punkt tag(centrum) √<br />

XML fejl: For f˚a/mange <br />

Kugle mangler farve tag<br />

l34<br />

31


Forventer fejlbesked om at der er for f˚a/mange farve tag. √<br />

XML fejl: For f˚a/mange <br />

Kugle mangler radius tag<br />

l33<br />

Forventer fejlbesked om for lidt/mange radius tag √<br />

XML fejl: For f˚a/mange <br />

Radius angivet som negativ værdi<br />

l33 <br />

Der forventes fejlbesked om at radius er angivet forkert √<br />

XML fejl: ’s r attribut i forkert format<br />

Krav: Plan skal have 3 punkter. Punkterne skal have id ”stedpunkt”, ”retningsvektor1”og<br />

”retningsvektor2”. Punktet, og de to vektorer, skal definere et plan.<br />

Forkert id angivet<br />

l15 <br />

Forventer fejlbesked om forkert id √<br />

XML fejl: Forkert id attribut i <br />

Angiver kun 2 punkt attributter<br />

l15<br />

Forventer en fejlbesked om for lidt/f˚a punkt attributter √<br />

XML fejl: tillader kun 3 x <br />

De 2 punkter ligger p˚a linie<br />

l15 <br />

l16 <br />

l17 <br />

Forventer fejlbesked om at plan ikke definerer plan √<br />

XML fejl: Vektorer og punktet i definere ikke et plan<br />

To punkter ligger p˚a samme sted<br />

l15 <br />

l16 <br />

l17 <br />

Forventer fejlbesked om at plan ikke definerer et plan √<br />

XML fejl: Vektorer og punktet i definere ikke et plan<br />

Krav: Mesh skal have ”punkter”tag som definerer "antal_punkter" vis værdi skal være<br />

positivt heltal, dette antal skal passe overens med antallet af punkter. ”punkt”skal have id<br />

32


med værdi 0 til antal punkt. Mesh skal have gyldig farve tag<br />

Mesh mangler ”punkter”tagget<br />

l21<br />

Forventer fejlbesked om at punkter tagget mangler √<br />

XML fejl: for f˚a/mange <br />

Antallet af punkter stemmer ikke overens.<br />

l21 <br />

Forventer fejlbesked om forkert antal punkter √<br />

XML fejl: Ikke samstemmende antal punkter i <br />

Antallet angivet i bogstaver<br />

l21 <br />

Forventer fejlbesked om at antallet er angivet i forkert format √<br />

XML fejl: ’s antal_punkter i forkert format<br />

Ugyldig id værdi<br />

l22 <br />

Forventer fejlbesked om at id er angivet forkert √<br />

XML fejl: mangler id attribut,eller i forkert format<br />

Mangler farve tag<br />

l20<br />

Forventer fejlbesked om manglende farve tag √<br />

XML fejl: For mange/f˚a <br />

Krav: Mesh’s Trekanter tag har følgende krav<br />

• Skal have en attribut ”antal trekanter”, vis værdi er angivet i positive heltal.<br />

• Skal have liges˚a mange ”trekant”tags som ”antal trekanter”angiver.<br />

• ”trekant”skal have p1/p2/p3 attributter, disse skal have gyldige referencer til et punkt<br />

id.<br />

Mangler ”antal trekanter”attributten<br />

l27 <br />

Forventer fejlbesked om at ”antal trekanter”mangler √<br />

XML fejl: mangler antal_trekanter attribut<br />

Antallet af ”trekanter”stemmer ikke overens med hvad angivet i ”antal trekanter”<br />

l27 <br />

Forventer fejlbesked om at antallet ikke stemmer overens √<br />

XML fejl: Ikke samstemmende antal trekanter i <br />

33


Mangler en p1 attribut<br />

l128 <br />

Forventer om fejlbesked om at en p? attribut mangler √<br />

XML fejl: ’s p1/p2/p3 attribut mangler/forkert format<br />

p1 refererer til ugyldig id<br />

l128 <br />

Forventer fejlbesked om forkert reference/format √<br />

XML fejl: ’s p1/p2/p3 attribut mangler/forkert format<br />

Krav: Pilotsyn skal definere sine hoejde/bredde attributter, disse skal være positive heltal<br />

med mindsteværdien 1. Desuden skal det have et unikt id. Pilotsyn skal definere 4 punkt<br />

tag med følgende id, ”pilotoeje”, ”cockpitvindue stedpunkt”, ”cockpitvindue lodret”og ”cockpitvindue<br />

vandret”. De tre sidste punkt tags skal definere et plan.<br />

Pilotsyn definerer ikke hoejde<br />

l3 <br />

Forventer fejlbesked om at hoejde ikke er angivet √<br />

XML fejl: ’s hoejde/bredde ikke i korrekt format<br />

Pilotsyn definerer hoejde med ugyldig værdi<br />

l3 <br />

Forventer fejlbesked om at hoejde er angivt med forkert værdi √<br />

XML fejl: ’s hoejde/bredde skal være positive<br />

Pilotoeje har ikke unikt id<br />

37 <br />

38 <br />

39 <br />

40 <br />

41 <br />

42 <br />

43 <br />

Forventer fejlbesked om at id ikke er unikt √<br />

XML fejl: mangler unik id attribut<br />

Pilotoeje definere ikke pilotoeje<br />

l4<br />

Forventer fejlbesked om at pilotsyn mangler √<br />

XML fejl: Mangler i .<br />

Krav: Sol m˚a kun indeholde et farve tag og et punkt tag<br />

Sol indeholder 2 farve tags<br />

l10.5 <br />

34


Forventer fejlbesked om for mange farve tags √<br />

XML fejl: For mange/f˚a <br />

Sol indeholder ikke noget punkt tag<br />

l11<br />

Forventer fejlbesked om mangel p˚a punkt tag √<br />

XML fejl: For f˚a/mange <br />

7.5 Konklusion<br />

Afprøvningen viste hvad vi ogs˚a havde forventet og omtalt i afsnit 2, at n˚ar talværdier bliver<br />

ekstremt store kan der være fejl i udregningen af nuancen. Derudover blev der fundet et par<br />

stavefejl, men ellers forløb afprøvningen problemfrit. Ergo er alle vores krav opfyldt.<br />

35


A UML diagrammer<br />

A.1 Usecase diagram<br />

Bruger Lav Billed<br />

36<br />

Fly<strong>Simulator</strong>


A.2 Klassediagram<br />

Kanvas<br />

-kanvas : Color[][]<br />

+setPixel()<br />

+skrivPPM()<br />

Kugle<br />

1<br />

KameraVinkler<br />

-kamera : Kamera[]<br />

+tagSerie(in Scene)<br />

Kamera<br />

-film : Kanvas<br />

+klik(in Scene)<br />

1..*<br />

Figur er abstrakt, metoden<br />

nuance er fælles for alle<br />

klasserne her, mens de to<br />

andre, er abstrakt defineret.<br />

Plan<br />

1<br />

KameraVinkler bruger ikke<br />

direkte Scene, men giver<br />

den videre til Kamera<br />

indeholder<br />

37<br />

Trekant<br />

-figur : Figur[]<br />

-sol : Sol<br />

Scene<br />

+nuance(in Punkt, in Vektor) : Color<br />

1<br />

0..*<br />

Figur<br />

+skaeringspunkt(in Vektor, in Punkt)<br />

+nuance(in skæringspunkt : Punkt, in øje : Punkt, in Sol) : Color<br />

+findNormalvektor(in Vektor, in Punkt)<br />

0..*<br />

1<br />

Sol<br />

-farve : Color<br />

-punkt : Punkt<br />

Mesh<br />

-trekanter : Trekant[]


A.3 Sekvensdiagram<br />

Fly<strong>Simulator</strong><br />

new XMLParser(filsti:String)<br />

s := hentScene()<br />

KameraVinkler := hentKameraVinkler()<br />

tagSerie(s)<br />

XMLParser<br />

XMLParser skaber Kamera<br />

og Scene objektet, derfor<br />

findes de først, når<br />

XMLParser startes op<br />

KameraVinkler Kamera<br />

Scene<br />

k = Kamera[]<br />

er en attribut til<br />

KameraVinkler<br />

38<br />

*[i := 0...k.length] klik(s)<br />

h = højde af billed<br />

b = bredde af billed<br />

Er attributter<br />

til Kamera<br />

*[i:= 1...h, i:= 1...b] nuance(p,v) : Color<br />

Color<br />

Kanvas.skrivPPM<br />

Udskrivning til PPM filformat<br />

sker i klassen Kanvas, dette<br />

er dog udeladt for simplicitet


A.4 Sekvensdiagram for Scene<br />

Kamera Scene<br />

nuance(Punkt øje, Vektor v) : Color<br />

Hvis p er null, dvs, der ikke<br />

blev fundet noget skææringspunkt,<br />

returnere Scene<br />

Ellers ses om der ligger noget<br />

imellem Sol.position og p (skygge)<br />

Hvis ikke, udregnes farven for p<br />

* [i := 0...figur.length] p := skæringspunkt(Punkt øje, Vektor v)<br />

[p == null] [p != null] s := lavVektor(Sol.position,p)<br />

* [i := 0...figur.length] sk := skæringspunkt(Sol.position,s)<br />

[sk != p] [sk==p] nuance(p,v,Sol) : Color<br />

Farve udregning sker kun for<br />

den figur som blev ramt.<br />

Scene holder en reference<br />

til denne figur.<br />

39<br />

Figur Vektor<br />

findNormalvektor(p,v)


B CRC Kort<br />

Denne section har de forskellige CRC kort som vi har lavet under udviklings processen.<br />

Figur CRC kort<br />

Figur<br />

At levere de matematisk funktioner<br />

og udregninger, som i forbindelse med<br />

str˚alesporing, vil være ens for alle repræsentationer<br />

af elementer i domænet<br />

40<br />

Vektor, enkelte nedarvede klasse (fx.<br />

Kugle)


Fly<strong>Simulator</strong> CRC kort<br />

Fly<strong>Simulator</strong><br />

At sørger for at argumentet til programmet<br />

er korrekt, dvs. at der findes et filnavn,<br />

som vi kan bruge som input<br />

At sørger for at kaldet til XMLParser<br />

sker, s˚aledes at Scene og KameraVinkler<br />

bliver lavet<br />

At sørger for at KameraVinkler starter<br />

med at tegne billederne<br />

41<br />

XMLParser<br />

KameraVinkler


Kamera CRC kort<br />

Kamera<br />

At opbygge de str˚aler, som der skal spores<br />

Sørger for at de opbyggede vektorer bliver<br />

str˚alesporet<br />

Sørger for at de farver, som bliver<br />

str˚aletsporet, bliver overgivet til Kanvas<br />

klassen<br />

42<br />

Vektor<br />

Scene<br />

Kanvas


KameraVinkler CRC kort<br />

Kamera<br />

At holde styr p˚a alle de Kamera som er<br />

blevet givet som input<br />

At disse modtager et Scene objekt, og<br />

give det videre til Kamera<br />

43


Kanvas CRC kort<br />

Kamera<br />

At sørger for at udskrive et konkret billed,<br />

i PPM format<br />

44


Kugle CRC kort<br />

Kugle<br />

At sørger for at levere den nødvendige<br />

kode, for at kunne udregne normal vektoreren<br />

for denne type figur<br />

Sørger for at man kan finde et skæringspunkt<br />

i denne type figur<br />

45<br />

Vektor, Punkt<br />

Vektor, Punkt


Plan CRC kort<br />

Plan<br />

At sørger for at levere den nødvendige<br />

kode, for at kunne udregne normal vektoreren<br />

for denne type figur<br />

Sørger for at man kan finde et skæringspunkt<br />

i denne type figur<br />

46<br />

Vektor, Punkt<br />

Vektor, Punkt


Trekant CRC kort<br />

Trekant<br />

Sørger for at levere en normalvektor for Plan, Vektor, Punkt<br />

trekanten.<br />

Sørger for at kunne finde skæringspunkt Vektor, Punkt<br />

47


Mesh CRC kort<br />

Mesh<br />

Sørger for at kunne levere en normalvektor<br />

for et punkt p˚a meshet<br />

Sørger for at man kan finde et skærings<br />

punkt, givet en vektor og et punkt<br />

48<br />

Trekant, Vektor, Punkt<br />

Trekant, Vektor, Punkt


Punkt CRC kort<br />

Punkt<br />

At opbevarer information omkring et<br />

punkt<br />

49


Scene CRC kort<br />

Scene<br />

At sørger for at holde styr p˚a sine figurer,<br />

og solen<br />

At kunne finde farven, for et punkt, givet<br />

en vektor, og et punkt<br />

50<br />

Figur, Vektor, Punkt


Sol CRC kort<br />

Sol<br />

At opbevarer information omkring solen.<br />

Stedpunkt og farve<br />

51<br />

Punkt, Color


Vektor CRC kort<br />

Vektor<br />

At opbevarer information omkring en<br />

vektor<br />

At levere de matematiske funktioner,<br />

som omhandler vektor udregning<br />

52


XMLParser CRC kort<br />

XMLParser<br />

At sørger for at instantiere de<br />

ovenst˚aende elementer<br />

At sørger for at inddata er korrekt. At<br />

punkter til trekant fx. definere en trekant,<br />

og at cockpitvindue definere et<br />

plan<br />

Vektor, Punkt<br />

At fortælle om fejl XMLParseError<br />

53


C XML specifikation<br />

XML Specifikation<br />

Tag Undertag Attributter<br />

x,y,z og evt. id="navn"<br />

r,g,b<br />

r<br />

p1,p2,p3<br />

antal punkter="x"<br />

<br />

...x<br />

antal trekanter="x"<br />

<br />

...x<br />

id="navn"<br />

<br />

id="xxx"<br />

<br />

<br />

<br />

id="xxx"<br />

<br />

<br />

id="xxx"<br />

<br />

<br />

C.1 Krav til tags<br />

Disse specifikationer er taget fra opgaveformuleringen[2]<br />

Scene Inddata best˚ar først af en s˚akaldt tag, der beskriver hvilken XML-udgave vi bruger<br />

og hvilket tegnsæt. Dernæst kommer -taggen, den starter med og ender med<br />

, indenfor disse to beskrives selve scenen.<br />

Generelt gælder det at XML-tags, der indeholder andre XML-tags, skrives p˚a formen<br />

... andre tags....<br />

Tags, der ikke indeholder andre tags, kan skrives som<br />


Alle disse punkter defineres vha. -taggen, og gives deres navn vha id-attributten,<br />

dette vil ogs˚a blive navnet p˚a billedet. De tre koordinater skal betragtes som kommatal.<br />

Der kan være arbitrært mange pilotsyn i en scene, og der genereres et billede for hvert<br />

pilotsyn.<br />

sol Denne tag beskriver solens position og farve. Positionen beskrives vha -taggen,<br />

og er givet navnet position. Farven beskrives i -taggen, hvor r-attributten angiver<br />

mængden af rødt, g-attributten mængden af grøn og b-attributten mængden af bl˚a. Alle tre<br />

værdier løber mellem 0 og 255. Disse tal kan kun være heltallige.<br />

kugle Denne tag beskriver en kugle i scenen. Den har et centrum, der angivet som et punkt<br />

med navn centrum. Kuglen har ogs˚a farve, som angivet som beskrevet ovenfor. Kulgen har<br />

ogs˚a en radius. Den angivet med -taggen der har attributten r der giver radius af<br />

kuglen. Radius skal angives i kommatal.<br />

mesh Denne tag beskriver et trekantsgitter. I hvert mesh angives først en punktliste over de<br />

punkter, der indg˚ar i trekantsgitteret. Dernæst kommer en liste af trekanter hvor der i hver<br />

trekant gives tre indeks ind i punktlisten som svarer til de punkter trekanten udspændes af.<br />

Et mesh har ogs˚a farve, som angives som beskrevt ovenfor.<br />

Punktlisten angives som en -tag inden i hvilken punkterne st˚ar defineret fortløbende.<br />

har attributten antal punkter, der angiver hvor mange punkter der er i punktlisten.<br />

Hvert punkt er givet et id, der svarer til hvilket nummer det er i punktlisten.<br />

Trekantslisten angives som en -tag inden i hvilken punkterne st˚ar defineret<br />

fortløbende. har en attribut antal trekanter, der angiver hvor mange punkter<br />

der er i trekantslisten. En har attributter pi, p2 og p3, som angiver de tre<br />

indeks(heltal) i punktlisten, hvor trekantens punkter kan findes.<br />

plan Denne tag beskriver planer. Her menes der alts˚a planer med uendelige stor udstrækning.<br />

En plan er givet ved et stedpunkt(dvs et punkt hvorfra planen udspændes) og to retningsvektorer,<br />

som udspænder planen. Planen har ligesom de andre figurer en farve.<br />

55


D Afprøvningsdata<br />

D.1 Obligatoriske billeder<br />

Figur 7: Obligatoriske billede syn1<br />

56


Figur 8: Obligatoriske billede syn2<br />

57


Figur 9: Obligatoriske billede syn3<br />

58


D.2 Data til matematisk udregning af nuance<br />

Vinkel 0<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Vinkel 45<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

59


D.3 Data til opstilling i 3 dimensioner<br />

D.3.1 Test 3a<br />

Inddata<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Uddata<br />

D.3.2 Test 3b<br />

Inddata<br />

<br />

<br />

<br />

<br />

60


Figur 10: Test 3a<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

61


<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Uddata<br />

D.3.3 Test 3c<br />

Inddata<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Uddata<br />

62


D.3.4 Test 3d<br />

Inddata<br />

<br />

Figur 11: Test 3b<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

63


Figur 12: Test 3c<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

64


Uddata<br />

D.3.5 Test 3e<br />

Inddata<br />

<br />

Figur 13: Test 3d<br />

<br />

<br />

<br />

<br />

65


<br />

<br />

<br />

<br />

<br />

<br />

<br />

Uddata<br />

D.3.6 Test 3f<br />

Inddata<br />

<br />

Figur 14: Test 3e<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

66


<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Uddata<br />

D.3.7 Test 3g<br />

Inddata<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

67


Figur 15: Test 3f<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

68


Uddata<br />

D.3.8 Test 3h<br />

Inddata<br />

<br />

Figur 16: Test 3g<br />

<br />

<br />

<br />

<br />

<br />

<br />

69


<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Uddata<br />

D.3.9 Test 3i<br />

Inddata<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

70


Figur 17: Test 3h<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

71


<br />

Uddata<br />

Figur 18: Test 3i<br />

72


E Kildekode<br />

E.1 Figur.java<br />

0 import java . awt . Color ;<br />

1<br />

2 abstract public class Figur{<br />

3 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

4 Figur . java<br />

5<br />

6 Figur ( Color farve , double r e f l e k t i o n s k o e f f i c i e n t )<br />

7<br />

8 Constructor t i l o p r e t t e l s e en Figur , hvor f a r v e er farven p˚a f i g u r e n og<br />

9 r e f l e k t i o n s k o f f i c i e n t er r e f l e k t i o n s k o e f f i c i e n t e n f o r a l l e g r u n d f a r v e r .<br />

10<br />

11 a b s t r a c t Vektor findNormanvektor ( Punkt skaeringspunkt , Punkt o e j e )<br />

12<br />

13 r e t u r n e r e normalvektoren i f o r h o l d a f f i g u r e n , som a l t i d peger imod kameraet ,<br />

14 hvor s k a e r i n g s p u n k t er det s k æ r i n g s p u n k t e t mellem den a k t u e l l e g i t t e r v e k t o r<br />

15 og ø j e t f r a kameraet , og o e j e er ø j t f r a kameraet .<br />

16<br />

17 a b s t r a c t Punkt s k a e r i n g s p u n k t ( Vektor g i t t e r v e k t o r , Punkt o e j e )<br />

18<br />

19 r e t u r n e r e s k æ r i n g s p u n k t e t mellem f i g u r e n og den l i n j e som den a k t u e l l e<br />

20 g i t t e r v e k t o r og ø j e t f r a kameraet udgør .<br />

21<br />

22 Color nuance ( Punkt skaeringspunkt , Punkt oeje , Sol s o l )<br />

23<br />

24 r e t u r n e r e e t Color o b j e k t som i n d e h o l d e r den f a r v e som f i g u r e n har i<br />

25 skaeringspunkt , hvor o e j e er ø j e t f r a kameraet og s o l er s o l e n f r a Scene .<br />

26<br />

27 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

28<br />

29 // F i e l d s<br />

30 protected f i n a l Color f a r v e ;<br />

31 protected f i n a l double r e f l e k t i o n s k o e f f i c i e n t ;<br />

32 public static double r e f l e k t i o n s k o e f f i c i e n t D e f a u l t = 1 ;<br />

33<br />

34 // Constructors<br />

35 Figur ( Color farve , double r e f l e k t i o n s k o e f f i c i e n t ){<br />

36 this . f a r v e = f a r v e ;<br />

37 this . r e f l e k t i o n s k o e f f i c i e n t = r e f l e k t i o n s k o e f f i c i e n t ;<br />

38 }<br />

39 // Methods<br />

40 abstract public Vektor findNormalvektor ( Punkt skaeringspunkt , Punkt o e j e ) ;<br />

41 abstract public Punkt skaeringspunkt ( Vektor g i t t e r v e k t o r , Punkt o e j e ) ;<br />

42<br />

43 public Color nuance ( Punkt skaeringspunkt , Punkt oeje , Sol s o l ){<br />

44 // f i n d e r normalvektoren t i l f i g u r e n .<br />

45 Vektor normalvektor = findNormalvektor ( skaeringspunkt , o e j e ) ;<br />

46<br />

47 // v e k t o r mellem s k a e r i n g s p u n k t og l y s k i l d e<br />

48 Vektor p T i l S o l = Vektor . lavVektor ( skaeringspunkt , s o l . p o s i t i o n ) ;<br />

73


49<br />

50 // Cos ( v i n k e l ) mellem normalvektor og p T i l S o l<br />

51 double cosVinkel = Vektor . skalarprodukt ( pTilSol , normalvektor ) /<br />

52 ( Vektor . laengde ( p T i l S o l ) ∗ Vektor . laengde ( normalvektor ) ) ;<br />

53<br />

54 // er cosVinkel < 0 , s˚a er punktet ramt b a g f r a i f o r h o l d t i l ø j e t og<br />

55 // der er d e r f o r i skygge .<br />

56 i f ( cosVinkel < 0){<br />

57 return Color . black ;<br />

58 }<br />

59<br />

60 // udregner l y s i n t e n s i t e t e n f o r hver f a r v e v æ r d i udfra formlen<br />

61 // f r a o p g a v e t e k s t e n s i d e 7 , n e d e r s t .<br />

62 double l y s i n t e n s i t e t R = ( s o l . f a r v e . getRed ( ) / 2 5 5 ) ∗<br />

63 r e f l e k t i o n s k o e f f i c i e n t ∗ cosVinkel ;<br />

64<br />

65 double l y s i n t e n s i t e t G = ( s o l . f a r v e . getGreen ( ) / 2 5 5 ) ∗<br />

66 r e f l e k t i o n s k o e f f i c i e n t ∗ cosVinkel ;<br />

67<br />

68 double l y s i n t e n s i t e t B = ( s o l . f a r v e . getBlue ( ) / 2 5 5 ) ∗<br />

69 r e f l e k t i o n s k o e f f i c i e n t ∗ cosVinkel ;<br />

70<br />

71 // udregner grundfarverne i punktet .<br />

72 int R = ( int ) ( f a r v e . getRed ( ) ∗ l y s i n t e n s i t e t R ) ;<br />

73 int G = ( int ) ( f a r v e . getGreen ( ) ∗ l y s i n t e n s i t e t G ) ;<br />

74 int B = ( int ) ( f a r v e . getBlue ( ) ∗ l y s i n t e n s i t e t B ) ;<br />

75<br />

76 // r e t u r n e r e nuancen i punktet .<br />

77 return new Color (R, G, B) ;<br />

78 }<br />

79 }<br />

74


E.2 Fly<strong>Simulator</strong>.java<br />

0 import java . i o . IOException ;<br />

1<br />

2 public class Fly<strong>Simulator</strong> {<br />

3 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

4 Fly<strong>Simulator</strong> . java<br />

5<br />

6 s t a t i c void main ( S t r i n g args [ ] )<br />

7<br />

8 Indgangs punkt .<br />

9<br />

10 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

11 public static void main ( S t r i n g [ ] a ) {<br />

12 S t r i n g x m l f i l = null ;<br />

13 i f ( a . length > 1) {<br />

14 System . out . p r i n t l n ( ”\ tFor mange argumenter \n\n” +<br />

15 ”\ tKorrekt brug : \ n” +<br />

16 ”\ t j a v a Fly<strong>Simulator</strong> xmlFilNavn \n\n” +<br />

17 ”\ txmlFilNavn er s t i e n p˚a XML input f i l e n , ”+<br />

18 ” angives i n t e t \n\targument , bruges ”+<br />

19 ”\” lufthavn2 . xml \” som input f i l . ”<br />

20 ) ;<br />

21 System . e x i t ( 0 ) ;<br />

22 } else i f ( a . length == 1) {<br />

23 x m l f i l = a [ 0 ] ;<br />

24 } else {<br />

25 x m l f i l = ” lufthavn2 . xml” ;<br />

26 }<br />

27 try {<br />

28 XMLParser p = new XMLParser( x m l f i l ) ;<br />

29 Scene scene = p . hentScene ( ) ;<br />

30 KameraVinkler kamera = p . hentKameraVinkler ( ) ;<br />

31 kamera . t a g S e r i e ( scene ) ;<br />

32 } catch ( XMLParseError exn ) {<br />

33 System . out . p r i n t l n ( ”XML f e j l : ” + exn . getMessage ( ) ) ;<br />

34 } catch ( IOException exn ) {<br />

35 System . out . p r i n t l n ( ” F i l f e j l : ” + exn . getMessage ( ) ) ;<br />

36 } catch ( RuntimeException exn ) {<br />

37 // kan b l i v e k a s t e t f r a scene , s k u l l e dog i k k e ske<br />

38 System . out . p r i n t l n ( ” Programfejl : ” + exn . getMessage ( ) ) ;<br />

39 }<br />

40 }<br />

41 }<br />

75


E.3 Kamera.java<br />

0 import java . awt . Color ;<br />

1 import java . i o . IOException ;<br />

2<br />

3 public class Kamera {<br />

4 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

5 Kamera . java<br />

6<br />

7 Kamera ( Punkt p , Punkt s , Vektor l , Vektor v , i n t h , i n t b , S t r i n g f i l )<br />

8<br />

9 Constructor t i l o p r e t t e l s e a f e t kamera . p er øjepunkt . Filmen dannes<br />

10 ud f r a Vektor l , v , s ( l o d r e t , vandret , s t e d p u n k t ) . h x b = højde x bredde<br />

11 f i l er navnet , p˚a f i l e n , som det e n d e l i g e b i l l e d gemmes i .<br />

12<br />

13 void k l i k ( Scene scene )<br />

14<br />

15 Tager b i l l e d , og gemmer i f i l .<br />

16<br />

17 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

18<br />

19 // f i e l d s<br />

20 private Punkt p ; // punkt , ø j e<br />

21 private Punkt s ; // s t e d p u n k t<br />

22 private Vektor l ; // l o d r e t v e k t o r<br />

23 private Vektor v ; // vandret v e k t o r<br />

24 private int h ; // højde a f b i l l e d<br />

25 private int b ; // bredde a f b i l l e d<br />

26 private S t r i n g f i l ; // f i l n a v n som der s k a l gemmes ned i<br />

27<br />

28 // d i s s e bruges t i l at holde s t y r p˚a procent baren<br />

29 private int antalPunkterBehandlet ;<br />

30 private double procentAfPunkter ;<br />

31 private int konsolBredde = 79;<br />

32 private int konsolIndex = 0 ;<br />

33 private int k o n s o l S i d s t = 0 ;<br />

34<br />

35 private Kanvas f i l m ; // h o l d e r f o r b i l l e d e<br />

36<br />

37 // g i t t e r som i n d e h o l d e r a l l e v e k t o r e r der s k a l spores<br />

38 private Vektor [ ] [ ] g i t t e r ;<br />

39 private Vektor s t e p l ; // s k r i d t hen a f l o d r e t vektoren , f o r hver p i x e l<br />

40 private Vektor s t e p v ; // s k r i d t hen a f vandret vektoren , f o r hver p i x e l<br />

41<br />

42 // constructor , kun en c o n s t r u c t o r t i l Kamera<br />

43 public Kamera( Punkt p , Punkt s , Vektor l , Vektor v ,<br />

44 int h , int b , S t r i n g f i l ) {<br />

45<br />

46 this . p = p ;<br />

47 this . s = s ;<br />

48 this . l = l ;<br />

49 this . v = v ;<br />

50 this . h = h ;<br />

76


51 this . b = b ;<br />

52 this . f i l = f i l ;<br />

53<br />

54 antalPunkterBehandlet = 0 ;<br />

55 procentAfPunkter = 1 0 0 . 0 / ( h ∗ b ) ;<br />

56<br />

57 g i t t e r = new Vektor [ h ] [ b ] ;<br />

58 f i l m = new Kanvas (h , b , Color . black ) ;<br />

59<br />

60 // h v i s b/h er ligmed en , s k a l der t a g e s nogle s æ r l i g e f o r h o l d ,<br />

61 // s˚a l e d e s at g i t t e r punkterne kommer t i l at l i g g e r i g t i g t .<br />

62 i f ( h == 1){<br />

63 s t e p l = new Vektor ( 0 , 0 , 0 ) ;<br />

64 } else {<br />

65 h−−;<br />

66 s t e p l = new Vektor ( l . x / ( h ) , l . y / h , l . z / ( h ) ) ;<br />

67 h++;<br />

68 }<br />

69<br />

70 i f ( b == 1) {<br />

71 s t e p v = new Vektor ( 0 , 0 , 0 ) ;<br />

72 } else {<br />

73 b−−;<br />

74 s t e p v = new Vektor ( v . x / ( b ) , v . y / b , v . z / ( b ) ) ;<br />

75 b++;<br />

76 }<br />

77<br />

78 // se e v t . program b e s k r i v e l s e f o r y d e r l i g e r e d e t a l j e r .<br />

79 for ( int i = 0 ; i < h ; i ++){<br />

80 /∗ i n d r e r l ø k k e s t a r t ∗/<br />

81 for ( int i 2 = 0 ; i 2 < b ; i 2++){<br />

82 Punkt gitterPunkt = Vektor . t i l P u n k t (<br />

83 Vektor . adder (<br />

84 Vektor . lavVektor ( s ) ,<br />

85 Vektor . adder (<br />

86 Vektor . s k a l e r ( s t e p l , h−( i +1)) ,<br />

87 Vektor . s k a l e r ( step v , i 2 )<br />

88 )<br />

89 )<br />

90 ) ;<br />

91 g i t t e r [ i ] [ i 2 ] = Vektor . lavVektor (p , gitterPunkt ) ;<br />

92 }<br />

93 /∗ i n d r e r l ø k k e s l u t ∗/<br />

94 }<br />

95 }<br />

96<br />

97 private void updaterBar ( ) {<br />

98 int konsolNu = ( int ) Math . round ( 0 . 7 9 ∗<br />

99 ( procentAfPunkter ∗ antalPunkterBehandlet ) ) ;<br />

100<br />

101 int k o n s o l D i f f = Math . abs ( k o n s o l S i d s t − konsolNu ) ;<br />

102<br />

103 while (−− k o n s o l D i f f > −1) {<br />

77


104 System . out . p r i n t ( ”#” ) ;<br />

105 }<br />

106 k o n s o l S i d s t = konsolNu ;<br />

107 }<br />

108<br />

109 public void k l i k ( Scene scene ) {<br />

110 System . out . p r i n t l n ( ”% a f ” + f i l + ” . ppm f a e r d i g ” ) ;<br />

111 System . out . p r i n t l n ( ”0%−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−50”+<br />

112 ”%−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−100%” ) ;<br />

113<br />

114 for ( int i = 0 ; i < h ; i ++) {<br />

115 for ( int j = 0 ; j < b ; j ++) {<br />

116 Color c = scene . nuance (p , g i t t e r [ i ] [ j ] ) ;<br />

117 f i l m . s e t P i x e l ( j , i , c ) ;<br />

118 antalPunkterBehandlet++;<br />

119 updaterBar ( ) ;<br />

120 }<br />

121 }<br />

122 try {<br />

123 f i l m . skrivPPM( f i l ) ;<br />

124 System . out . p r i n t l n ( ”\n” + f i l +<br />

125 ” . ppm s k r e v e t t i l f i l \n” ) ;<br />

126 }<br />

127 catch ( IOException exn ) {<br />

128 System . out . p r i n t l n ( ” F e j l ved udskrivning a f b i l l e d e : ” +<br />

129 exn . getMessage ( ) + ”\n” ) ;<br />

130 }<br />

131 }<br />

132 }<br />

78


E.4 KameraVinkler.java<br />

0 public class KameraVinkler {<br />

1 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

2 KameraVinkler . java<br />

3<br />

4 KameraVinkler(Kamera [ ] kamera )<br />

5<br />

6 Constructor t i l o p r e t t e l s e a f e t KameraVinkler o b j e k t .<br />

7<br />

8 void t a g S e r i e ( Scene scene )<br />

9<br />

10 Tager a l l e kamera o b j e k t e r , og t a g e r e t b i l l e d a f scene , g i v e t<br />

11 de f o r s k e l l i g e synspunkter .<br />

12<br />

13 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

14 private Kamera [ ] kamera ;<br />

15<br />

16 public KameraVinkler ( Kamera [ ] kamera ) {<br />

17 this . kamera = kamera ;<br />

18 }<br />

19<br />

20 public void t a g S e r i e ( Scene scene ) {<br />

21 for ( int i = 0 ; i < kamera . length ; i ++) {<br />

22 kamera [ i ] . k l i k ( scene ) ;<br />

23 }<br />

24 }<br />

25 }<br />

79


E.5 Kanvas.java<br />

0 import java . awt . ∗ ;<br />

1 import java . i o . ∗ ;<br />

2<br />

3 public class Kanvas{<br />

4 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

5 Kanvas . java<br />

6<br />

7 Kanvas k l a s s e n er i k k e ændret i f o r h o l d t i l den u d l e v e r e d e form .<br />

8 Kun h e n v i s n i n g e r t i l S t ø r r e l s e s f e j l er ændret , p l u s k l a s s e n<br />

9 er f j e r n e t f r a packege k2 .<br />

10<br />

11 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

12 private Color [ ] [ ] kanvas ;<br />

13 private int højde = 0 ;<br />

14 private int bredde = 0 ;<br />

15 private int a n t a l B i l l e d e r = 1 ;<br />

16<br />

17 public Kanvas ( int højde , int bredde , int gr˚atone )<br />

18 {<br />

19 this ( højde , bredde , new Color ( gr˚atone , gr˚atone , gr˚atone ) ) ;<br />

20 }<br />

21<br />

22 public Kanvas ( int højde , int bredde , int rød , int grøn , int bl˚a )<br />

23 {<br />

24 this ( højde , bredde , new Color ( rød , grøn , bl˚a ) ) ;<br />

25 }<br />

26<br />

27 // The c o n s t r u c t o r doing something .<br />

28<br />

29 public Kanvas ( int højde , int bredde , Color f a r v e )<br />

30 {<br />

31 højde = højde ;<br />

32 bredde = bredde ;<br />

33 kanvas = new Color [ højde ] [ bredde ] ;<br />

34 setBaggrund ( f a r v e ) ;<br />

35 }<br />

36<br />

37 public void setBaggrund ( int gr˚atone )<br />

38 {<br />

39 setBaggrund (new Color ( gr˚atone , gr˚atone , gr˚atone ) ) ;<br />

40 }<br />

41<br />

42 public void setBaggrund ( int rød , int grøn , int bl˚a )<br />

43 {<br />

44 setBaggrund (new Color ( rød , grøn , bl˚a ) ) ;<br />

45 }<br />

46<br />

47 public void setBaggrund ( Color f a r v e )<br />

48 {<br />

49 for ( int i = 0 ; i < højde ; i ++)<br />

50 for ( int j = 0 ; j < bredde ; j++)<br />

80


51 kanvas [ i ] [ j ] = f a r v e ;<br />

52 }<br />

53<br />

54 public void s e t P i x e l ( int x , int y , int gr˚atone )<br />

55 {<br />

56 s e t P i x e l ( x , y , new Color ( gr˚atone , gr˚atone , gr˚atone ) ) ;<br />

57 }<br />

58<br />

59 public void s e t P i x e l ( int x , int y , int rød , int grøn , int bl˚a )<br />

60 {<br />

61 s e t P i x e l ( x , y , new Color ( rød , grøn , bl˚a ) ) ;<br />

62 }<br />

63<br />

64 public void s e t P i x e l ( int x , int y , Color f a r v e )<br />

65 {<br />

66 kanvas [ y ] [ x ] = f a r v e ;<br />

67 }<br />

68<br />

69 public Color g e t P i x e l ( int x , int y )<br />

70 {<br />

71 return kanvas [ x ] [ y ] ;<br />

72 }<br />

73<br />

74 public void mix ( Kanvas k )<br />

75 {<br />

76 i f ( ( højde ! = k . højde ) | | ( bredde ! = k . bredde ) )<br />

77 throw new S t o e r r e l s e s f e j l ( ” B i l l e d e r ikke samme s t ø r r e l s e ” ) ;<br />

78 for ( int i = 0 ; i < højde ; i ++)<br />

79 for ( int j = 0 ; j < bredde ; j ++)<br />

80 kanvas [ i ] [ j ] =<br />

81 new Color ( ( kanvas [ i ] [ j ] . getRed ( ) ∗ a n t a l B i l l e d e r +<br />

82 k . g e t P i x e l ( i , j ) . getRed ( ) ) / ( a n t a l B i l l e d e r + 1) ,<br />

83 ( kanvas [ i ] [ j ] . getGreen ( ) ∗ a n t a l B i l l e d e r +<br />

84 k . g e t P i x e l ( i , j ) . getGreen ( ) ) / ( a n t a l B i l l e d e r + 1) ,<br />

85 ( kanvas [ i ] [ j ] . getBlue ( ) ∗ a n t a l B i l l e d e r +<br />

86 k . g e t P i x e l ( i , j ) . getBlue ( ) ) / ( a n t a l B i l l e d e r + 1 ) ) ;<br />

87 a n t a l B i l l e d e r ++;<br />

88 }<br />

89<br />

90<br />

91 public void skrivPPM( S t r i n g f i l n a v n ) throws IOException<br />

92 {<br />

93 PrintWriter u d f i l = new PrintWriter (new F i l e W r i t e r ( f i l n a v n+” .ppm” ) ) ;<br />

94 Color p i x e l ;<br />

95<br />

96 u d f i l . p r i n t l n ( ”P3” ) ;<br />

97 u d f i l . p r i n t l n ( bredde + ” ” + højde ) ;<br />

98 u d f i l . p r i n t l n ( ”255” ) ;<br />

99 u d f i l . p r i n t l n ( ) ;<br />

100<br />

101 for ( int i = 0 ; i < højde ; i++)<br />

102 for ( int j = 0 ; j < bredde ; j++)<br />

103 {<br />

81


104 p i x e l = kanvas [ i ] [ j ] ;<br />

105 u d f i l . p r i n t l n ( p i x e l . getRed ( ) + ” ” + p i x e l . getGreen ( ) + ” ” +<br />

106 p i x e l . getBlue ( ) ) ;<br />

107 }<br />

108 u d f i l . c l o s e ( ) ;<br />

109 }<br />

110<br />

111 public static void main ( S t r i n g [ ] args )<br />

112 {<br />

113 System . out . p r i n t l n ( ”\n\nINTERN AFPRØVNING AF: K2/Kanvas\n\n” ) ;<br />

114<br />

115 Kanvas t0 = new Kanvas ( 2 0 , 1 0 , 4 2 ) ;<br />

116 // t r y { t0 . skrivPPM (” t0 ” ) ; }<br />

117 // catch ( IOException e ) { System . out . p r i n t l n ( e ) ; }<br />

118 System . out . p r i n t l n ( ” Ikke−k v a d r a t i s k kanvas o p r e t t e t . ” ) ;<br />

119<br />

120 Kanvas t1 = new Kanvas ( 2 0 , 2 0 , 1 2 7 ) ;<br />

121 System . out . p r i n t l n ( ” g e t P i x e l c e n t e r + gr˚a konstruktør : ” +<br />

122 t1 . g e t P i x e l ( 1 0 , 1 0 ) . e q u a l s<br />

123 (new Color ( 1 2 7 , 1 2 7 , 1 2 7 ) ) ) ;<br />

124<br />

125 Kanvas t2 = new Kanvas ( 2 0 , 2 0 , 0 , 1 0 , 2 5 5 ) ;<br />

126 System . out . p r i n t l n ( ” Getpixel h j ø r n e r + t r e t a l s k o n s t r u k t ø r : ” +<br />

127 t2 . g e t P i x e l ( 1 9 , 0 ) . e q u a l s ( t2 . g e t P i x e l ( 0 , 1 9 ) ) ) ;<br />

128<br />

129 Kanvas t3 = new Kanvas ( 2 0 , 2 0 , new Color ( 2 5 5 , 2 5 5 , 2 5 5 ) ) ;<br />

130 System . out . p r i n t l n ( ” f a r v e k o n s t r u k t ø r + c o l o r maxværdi : ” +<br />

131 t3 . g e t P i x e l ( 1 0 , 1 0 ) . e q u a l s (new Color ( 2 5 5 , 2 5 5 ,<br />

132 2 5 5 ) ) ) ;<br />

133 t3 . setBaggrund ( 1 2 7 ) ;<br />

134 System . out . p r i n t l n ( ”Gr˚a baggrund : ” +<br />

135 t3 . g e t P i x e l ( 1 0 , 1 0 ) . e q u a l s (new Color ( 1 2 7 , 1 2 7 ,<br />

136 1 2 7 ) ) ) ;<br />

137<br />

138 t3 . setBaggrund ( 1 2 7 , 1 2 8 , 1 2 9 ) ;<br />

139 System . out . p r i n t l n ( ” t r e t a l s b a g g r u n d : ” +<br />

140 t3 . g e t P i x e l ( 1 0 , 1 0 ) . e q u a l s (new Color ( 1 2 7 , 1 2 8 ,<br />

141 1 2 9 ) ) ) ;<br />

142<br />

143 t3 . setBaggrund (new Color ( 1 , 2 , 3 ) ) ;<br />

144 System . out . p r i n t l n ( ” farvebaggrund : ” +<br />

145 t3 . g e t P i x e l ( 1 0 , 1 0 ) . e q u a l s (new Color ( 1 , 2 ,<br />

146 3 ) ) ) ;<br />

147<br />

148 System . out . p r i n t l n ( ”\n\nGammelsmølf er en f a l l e r e t h a v e n i s s e . \ n\n” ) ;<br />

149<br />

150 t2 . s e t P i x e l ( 0 , 1 9 , 1 2 7 ) ;<br />

151 t2 . s e t P i x e l ( 1 9 , 0 , 1 2 0 , 1 3 0 , 1 4 0 ) ;<br />

152 t2 . s e t P i x e l ( 1 0 , 1 0 , new Color ( 0 , 0 , 0 ) ) ;<br />

153<br />

154 System . out . p r i n t l n ( ” s e t P i x e l hjørne og center , c o l o r minværdi : ”<br />

155 + ( t2 . g e t P i x e l ( 0 , 1 9 ) .<br />

156 e q u a l s (new Color (127 , 127 , 127)) &&<br />

82


157 t2 . g e t P i x e l ( 1 9 , 0 ) .<br />

158 e q u a l s (new Color (120 , 130 , 140)) &&<br />

159 t2 . g e t P i x e l ( 1 0 , 1 0 ) .<br />

160 e q u a l s (new Color ( 0 , 0 , 0 ) ) ) ) ;<br />

161<br />

162 System . out . p r i n t l n ( ”WriteBMP a f p r ø v e s ikke . Denne afprøvning ” +<br />

163 ” f o r s ø g e r at undg˚a at bruge d i s k . ” ) ;<br />

164<br />

165 try<br />

166 { t2 . s e t P i x e l ( 1 0 , 1 0 , 2 5 6 ) ; }<br />

167 catch ( IllegalArgumentException e )<br />

168 { System . out . p r i n t l n ( ” F a r v e f e j l f a n g e t : ” + e ) ; }<br />

169<br />

170 try<br />

171 { t2 . s e t P i x e l ( 1 0 , 2 0 , 2 5 5 ) ; }<br />

172 catch ( ArrayIndexOutOfBoundsException e )<br />

173 { System . out . p r i n t l n ( ” I n d e x f e j l f a n g e t : ” + e ) ; }<br />

174<br />

175 /∗ T i l s t a n d l i g e nu :<br />

176 t1 −− ren ( 1 2 7 , 1 2 7 , 1 2 7 )<br />

177 t2 −− ( 0 , 1 0 , 2 5 5 ) med<br />

178 ( 0 , 1 9 ) = ( 1 2 7 , 1 2 7 , 1 2 7 )<br />

179 ( 1 9 , 0 ) = ( 1 2 0 , 1 3 0 , 1 4 0 )<br />

180 ( 1 0 , 1 0 ) = ( 0 , 0 , 0 )<br />

181 t3 −− ren ( 1 , 2 , 3 )<br />

182 ∗/<br />

183<br />

184 t1 . mix ( t2 ) ;<br />

185 t1 . mix ( t3 ) ;<br />

186<br />

187 /∗<br />

188 t r y<br />

189 {<br />

190 t1 . skrivPPM (” t1 ” ) ;<br />

191 t2 . skrivPPM (” t2 ” ) ;<br />

192 t3 . skrivPPM (” t3 ” ) ;<br />

193 }<br />

194 catch ( IOException e )<br />

195 { System . out . p r i n t l n ( e ) ; }<br />

196<br />

197 ∗/<br />

198<br />

199 System . out . p r i n t l n ( ” Billedmix : ” +<br />

200 t1 . g e t P i x e l ( 7 , 7 ) . e q u a l s (new Color ( 4 2 , 4 6 ,<br />

201 1 2 8 ) ) ) ;<br />

202<br />

203<br />

204 /∗ Ekstern afprøvning . Skal l a v e 1 0 høj , 3 0 bred kanvas , med<br />

205 p r i k i ( 9 , 1 ) , dvs . p˚a n æ s t ø v e r s t e l i n i e . ∗/<br />

206<br />

207 Kanvas t4 = new Kanvas ( 1 0 , 3 0 , 2 0 0 ) ;<br />

208 t4 . s e t P i x e l ( 9 , 1 , 0 ) ;<br />

209 /∗ t r y { t4 . skrivPPM (” t4 ” ) ; }<br />

83


210 catch ( IOException e ) { } ; ∗/<br />

211<br />

212<br />

213 }<br />

214<br />

215 }<br />

84


E.6 Kugle.java<br />

0 import java . awt . Color ;<br />

1<br />

2 public class Kugle extends Figur{<br />

3 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

4 Kugle . java<br />

5<br />

6 Kugle ( Punkt centrum , double radius , Color f a r v e )<br />

7<br />

8 Constructor s æ t t e r k u g l e n s r e f l e k t i o n s k o e f f i c i e n t t i l<br />

9 d e f a u l t v æ r d i e n a n g i v e t i Figur k l a s s e n<br />

10<br />

11 Kugle ( Punkt centrum , double radius , Color farve , double r e f l e k t i o n s k o e f f i c i e n t )<br />

12<br />

13 Constructor s æ t t e r k u g l e n s r e f l e k t i o n s k o e f f i c i e n t t i l<br />

14 parameteren r e f l e k t i o n s k o e f f i c i e n t , som a n g i v e s f r a 0 t i l 1 .<br />

15<br />

16 Vektor findNormalvektor ( Punkt skaeringspunkt , Punkt o e j e )<br />

17<br />

18 Finder normalvektoren f o r en k u g l e i s k æ r i n g s p u n k t e t<br />

19 mellem kuglen og l i n i e n .<br />

20<br />

21 Punkt s k a e r i n g s p u n k t ( Vektor vektor , Punkt o e j e ) {<br />

22<br />

23 Udregner e v e n t u e l l e skæringspunkter mellem kuglen og l i n i e n<br />

24 d e f i n e r e t a f parametrene v e k t o r og o e j e .<br />

25<br />

26 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

27 // f i e l d s<br />

28 private Punkt centrum ; // Kuglens centrum<br />

29 private double r a d i u s ; // Kuglens r a d i u s<br />

30 private Color f a r v e ; // Kuglens f a r v e<br />

31<br />

32 // c o n s t r u c t o r s<br />

33<br />

34 public Kugle ( Punkt centrum , double radius , Color f a r v e ) {<br />

35 this ( centrum , radius , farve , Figur . r e f l e k t i o n s k o e f f i c i e n t D e f a u l t ) ;<br />

36 }<br />

37<br />

38 public Kugle ( Punkt centrum , double radius , Color farve ,<br />

39 double r e f l e k t i o n s k o e f f i c i e n t ) {<br />

40 super ( farve , r e f l e k t i o n s k o e f f i c i e n t ) ;<br />

41 this . centrum = centrum ;<br />

42 this . r a d i u s = r a d i u s ;<br />

43 this . f a r v e = f a r v e ;<br />

44 }<br />

45<br />

46 // methods<br />

47<br />

48 public Vektor findNormalvektor ( Punkt skaeringspunkt , Punkt o e j e ) {<br />

49 Vektor temp = Vektor . lavVektor ( centrum , skaeringspunkt ) ;<br />

50<br />

85


51 // udregner h v i l k e n v e j normalvektoren s k a l vende i f o r h o l d t i l ø j e t<br />

52 // u d n y t t e s i det t i l f æ l d e , hvor noget a f kuglen l i g g e r inde i f i l m e n .<br />

53 i f ( Vektor . laengde (<br />

54 Vektor . subtraher ( Vektor . lavVektor ( o e j e ) ,<br />

55 Vektor . adder ( Vektor . lavVektor ( centrum ) ,<br />

56 temp ))) <<br />

57 Vektor . laengde (<br />

58 Vektor . subtraher ( Vektor . lavVektor ( o e j e ) ,<br />

59 Vektor . adder ( Vektor . lavVektor ( centrum ) ,<br />

60 Vektor . vend ( temp ) ) ) ) ) {<br />

61 return temp ;<br />

62 }<br />

63 else {<br />

64 return Vektor . vend ( temp ) ;<br />

65 }<br />

66 }<br />

67<br />

68 // Hjælpefunktion t i l skaeringspunkt , udregner skæringspunkt<br />

69 private Punkt t s k a l a r ( Punkt oeje , Vektor vektor , double x ) {<br />

70 Punkt sp = new Punkt ( o e j e . x+vektor . x∗x ,<br />

71 o e j e . y+vektor . y∗x ,<br />

72 o e j e . z+vektor . z ∗x ) ;<br />

73 return sp ;<br />

74 }<br />

75<br />

76 public Punkt skaeringspunkt ( Vektor vektor , Punkt o e j e ) {<br />

77 //a , b og c t i l l ø s n i n g a f a n d e n g r a d s l i g n i n g<br />

78 double a = ( vektor . x∗ vektor . x+vektor . y∗ vektor . y+vektor . z∗ vektor . z ) ;<br />

79 double b = 2∗( vektor . x ∗( o e j e . x−centrum . x)+vektor . y ∗( o e j e . y−centrum . y)+<br />

80 vektor . z ∗( o e j e . z−centrum . z ) ) ;<br />

81 double c = Math . pow ( ( o e j e . x−centrum . x ) ,2)+<br />

82 Math . pow ( ( o e j e . y−centrum . y ) ,2)+<br />

83 Math . pow ( ( o e j e . z−centrum . z ) ,2) −<br />

84 Math . pow( radius , 2 ) ;<br />

85 // Diskreminant<br />

86 double d = Math . pow(b ,2) − 4∗ a∗ c ;<br />

87 // Linien skærer kuglen 2 gange<br />

88 i f ( d>0) {<br />

89 // x1 og x2 er l i g n i n g e n s l ø s n i n g e r .<br />

90 double x1 = (−b−Math . s q r t ( d ) ) / ( 2 ∗ a ) ;<br />

91 double x2 = (−b+Math . s q r t ( d ) ) / ( 2 ∗ a ) ;<br />

92<br />

93 // t j e k k e r om x1 s k æ r i n g s p u n k t e t er t æ t t e r e p˚a end x2 s k æ r i n g s p u n k t e t<br />

94 // og om det er ude a f f i l m e n .<br />

95 i f ( x1 < x2 && x1 > 1.0){<br />

96 return t s k a l a r ( oeje , vektor , x1 ) ;<br />

97 }<br />

98 // da x1 i k k e kunne bruges t j e k k e s om x2 kan , ved at se om den er<br />

99 // ude a f f i l m e n .<br />

100 else i f ( x2 > 1.0){<br />

101 return t s k a l a r ( oeje , vektor , x2 ) ;<br />

102 }<br />

103 else {<br />

86


104 // begge punkter b e f i n d e r s i g enten bag ø j e t e l l e r f ø r f i l m e n .<br />

105 return null ;<br />

106 }<br />

107 }<br />

108 // Linien tangere kuglen .<br />

109 i f ( d==0) {<br />

110 double x1 = (−b−Math . s q r t ( d ) ) / ( 2 ∗ a ) ;<br />

111 i f ( x1>=0) {<br />

112 return t s k a l a r ( oeje , vektor , x1 ) ;<br />

113 }<br />

114 }<br />

115 // Linien skærer i k k e kuglen .<br />

116 return null ;<br />

117 }<br />

118 }<br />

87


E.7 Mesh.java<br />

0 import java . awt . Color ;<br />

1<br />

2 public class Mesh extends Figur{<br />

3 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

4 Mesh . java<br />

5<br />

6 Mesh ( Trekant [ ] t r e k a n t e r , Color f a r v e )<br />

7<br />

8 Constructor som kun k a l d e r den anden c o n s t r u c t o r .<br />

9 Ud over at den sender a l l e argumenter videre , s˚a sender den ogs˚a<br />

10 s t a t i c v a r i a b l e n ” r e f l e k t i o n s k o e f f i c i e n t D e f a u l t ” f r a Figur k l a s s e n med .<br />

11<br />

12 Mesh ( Trekant [ ] t r e k a n t e r , Color farve , double r e f l e k t i o n s k o e f f i c i e n t )<br />

13<br />

14 Constructor som i n s t a n c i e r e s i n s u p e r k l a s s e n , og o p r e t t e r e t mesh med<br />

15 best˚aende a f de t r e k a n t e r som f i n d e s i array ’ e t t r e k a n t e r .<br />

16<br />

17 Vektor findNormalvektor ( Punkt skaeringspunkt , Punkt o e j e )<br />

18<br />

19 r e t u r n e r e normalvektoren f o r den t r e k a n t som s i d s t u d e l e v e r e d e e t<br />

20 skæringspunkt .<br />

21<br />

22 Punkt s k a e r i n g s p u n k t ( Vektor g i t t e r v e k t o r , Punkt o e j e )<br />

23<br />

24 r e t u r n e r e s k æ r i n g s p u n k t e t mellem den l i n j e som g i t t e r v e k t o r og o e j e udgør<br />

25 og den t r e k a n t i meshet som l i g g e r t æ t t e s t p˚a o e j e .<br />

26<br />

27 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

28<br />

29 // F i e l d s<br />

30 private Trekant [ ] t r e k a n t e r ;<br />

31 private int sidstRamteTrekant = −1;<br />

32<br />

33 // Constructors<br />

34 public Mesh ( Trekant [ ] trekanter , Color f a r v e ){<br />

35 this ( trekanter , farve , Figur . r e f l e k t i o n s k o e f f i c i e n t D e f a u l t ) ;<br />

36 }<br />

37<br />

38 public Mesh ( Trekant [ ] trekanter , Color farve , double r e f l e k t i o n s k o e f f i c i e n t ){<br />

39 super ( farve , r e f l e k t i o n s k o e f f i c i e n t ) ;<br />

40 this . t r e k a n t e r = t r e k a n t e r ;<br />

41 }<br />

42<br />

43 // Methods<br />

44 public Vektor findNormalvektor ( Punkt skaeringspunkt , Punkt o e j e ){<br />

45 // meshet er b l e v e t b e d t om en normalvektor , f ø r det er b l e v e t b e d t om<br />

46 // e t skæringspunkt .<br />

47 i f ( sidstRamteTrekant == −1){<br />

48 throw new RuntimeException ( ”mesh kan ikke r e t u r n e r e en ” +<br />

49 ” normalvektor , da der ikke er ramt nogen trekant ” ) ;<br />

50 }<br />

88


51 // r e t u r n e r e normalvektoren f r a den t r e k a n t som s i d s t u d l e v e r e d e e t<br />

52 // skæringspunkt .<br />

53 return t r e k a n t e r [ sidstRamteTrekant ] . findNormalvektor ( skaeringspunkt ,<br />

54 o e j e ) ;<br />

55 }<br />

56<br />

57 public Punkt skaeringspunkt ( Vektor g i t t e r v e k t o r , Punkt o e j e ){<br />

58 // i n s t a n c i e r e de nødvendige arrays og v a r i a b l e r<br />

59 Punkt [ ] s k a e r i n g s p u n k t e r = new Punkt [ t r e k a n t e r . length ] ;<br />

60 double [ ] a f s t a n d e = new double [ t r e k a n t e r . length ] ;<br />

61 int k o r t e s t A f s t a n d = −1;<br />

62<br />

63 for ( int i = 0 ; i < t r e k a n t e r . length ; i ++){<br />

64 s k a e r i n g s p u n k t e r [ i ] = t r e k a n t e r [ i ] . skaeringspunkt ( g i t t e r v e k t o r ,<br />

65 o e j e ) ;<br />

66<br />

67 i f ( s k a e r i n g s p u n k t e r [ i ] ! = null ){<br />

68 a f s t a n d e [ i ] = Vektor . laengde ( Vektor . lavVektor ( oeje ,<br />

69 s k a e r i n g s p u n k t e r [ i ] ) ) ;<br />

70<br />

71 // t j e k k e r om der er en t r e k a n t i mesh ’ e t som er b l e v e t ramt .<br />

72 i f ( k o r t e s t A f s t a n d == −1){<br />

73 k o r t e s t A f s t a n d = i ;<br />

74 }<br />

75 // t j e k k e r om den nye a f s t a n d som er f u n d e t er mindre end den<br />

76 // som h i d t i l har været mindst .<br />

77 i f ( a f s t a n d e [ i ] < a f s t a n d e [ k o r t e s t A f s t a n d ] ) {<br />

78 k o r t e s t A f s t a n d = i ;<br />

79 }<br />

80 }<br />

81 }<br />

82 // der er ingen a f t r e k a n t e r n e som er b l e v e t b e r ø r t .<br />

83 i f ( k o r t e s t A f s t a n d == −1){<br />

84 return null ;<br />

85 }<br />

86 // r e t u r n e r e det skæringspunkt med den k o r t e s t e<br />

87 // a f s t a n d t i l ø j e t , og gemmer det t i l senere brug .<br />

88 else {<br />

89 // notere den s i d s t e t r e k a n t som b l e v ramt .<br />

90 sidstRamteTrekant = k o r t e s t A f s t a n d ;<br />

91 return s k a e r i n g s p u n k t e r [ k o r t e s t A f s t a n d ] ;<br />

92 }<br />

93 }<br />

94 }<br />

89


E.8 Plan.java<br />

0 import java . awt . Color ;<br />

1<br />

2 public class Plan extends Figur{<br />

3 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

4 Plan . java<br />

5<br />

6 Plan ( Punkt p , Vektor vektor1 , Vektor vektor2 , Color f a r v e )<br />

7<br />

8 Constructor som kun k a l d e r den anden c o n s t r u c t o r .<br />

9 Ud over at den sender a l l e argumenter videre , s˚a sender den ogs˚a<br />

10 s t a t i c v a r i a b l e n ” r e f l e k t i o n s k o e f f i c i e n t D e f a u l t ” f r a Figur k l a s s e n med .<br />

11<br />

12 p u b l i c Plan ( Punkt punkt , Vektor vektor1 , Vektor vektor2 , Color farve ,<br />

13 double r e f l e k t i o n s k o e f f i c i e n t )<br />

14<br />

15 Constructor som i n s t a n c i e r e s i n s u p e r k l a s s e , og udregner k o n s t a n t e r t i l<br />

16 repræsentatio n a f p l a n e t ved l i g n i n g e n : Ax + By + Cy + D = 0 , og<br />

17 som udregner en normalvektor t i l p l a n e t .<br />

18<br />

19 Punkt s k a e r i n g s p u n k t ( Vektor g i t t e r v e k t o r , Punkt o e j e )<br />

20<br />

21 r e t u r n e r e s k æ r i n g s p u n k t e t f o r p l a n e t og den l i n j e som g i t t e r v e k t o r<br />

22 og o e j e udgør . Der gælder f o r s k æ r i n g s p u n k t e t at det i k k e m˚a l i g g e<br />

23 bag filmen , og at der d e r f o r i k k e r e t u r n e s e t skæringspunkt hvor<br />

24 g i t t e r v e k t o r s s k a l a r < 1.<br />

25<br />

26 Vektor findNormalvektor ( Punkt skaeringspunkt , Punkt o e j e )<br />

27<br />

28 r e t u r n e r e normalvektoren f o r p l a n e t som peger imod oeje , hvor o e j e<br />

29 er ø j e t f r a kameraet og s k a e r i n g s p u n k t er s k æ r i n g s p u n k t e t f o r<br />

30 f i g u r e n og den l i n j e som den a k t u e l l e g i t t e r v e k t o r og o e j e udgør .<br />

31<br />

32 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

33<br />

34 // F i e l d s<br />

35 private f i n a l double A, B, C, D;<br />

36 private f i n a l Vektor normalvektor ;<br />

37<br />

38 // Constructors<br />

39 // ved k a l d uden r e f l e k t i o n s k o e f f i c i e n t a n g i v e t .<br />

40 public Plan ( Punkt p , Vektor vektor1 , Vektor vektor2 , Color f a r v e ){<br />

41 this (p , vektor1 , vektor2 , farve , Figur . r e f l e k t i o n s k o e f f i c i e n t D e f a u l t ) ;<br />

42 }<br />

43<br />

44 // ved k a l d med r e f l e k t i o n s k o e f f i c i e n t a n g i v e t .<br />

45 public Plan ( Punkt punkt , Vektor vektor1 , Vektor vektor2 , Color farve ,<br />

46 double r e f l e k t i o n s k o e f f i c i e n t ){<br />

47 super ( farve , r e f l e k t i o n s k o e f f i c i e n t ) ;<br />

48 normalvektor = Vektor . krydsprodukt ( vektor1 , vektor2 ) ;<br />

49<br />

50 // udregner k o n s t a n t e r t i l repræsentatio n a f p l a n e t ved l i g n i n g e n :<br />

90


51 // Ax + By + Cz + D = 0<br />

52 A = normalvektor . x ;<br />

53 B = normalvektor . y ;<br />

54 C = normalvektor . z ;<br />

55 D = − A ∗ punkt . x − B ∗ punkt . y − C ∗ punkt . z ;<br />

56 }<br />

57<br />

58 // Methods<br />

59 public Punkt skaeringspunkt ( Vektor g i t t e r v e k t o r , Punkt o e j e ){<br />

60 // f i n d e r nævneren i l i g n i n g e n p˚a opgaveformuler ing ens s i d e 9 , ø v e r s t .<br />

61 double naevner = A ∗ g i t t e r v e k t o r . x + B ∗ g i t t e r v e k t o r . y + C ∗<br />

62 g i t t e r v e k t o r . z ;<br />

63<br />

64 // er nævneren 0 , s˚a er p l a n e t og l i n j e n p a r a l e l l e og skærer i k k e<br />

65 // hinanden .<br />

66 i f ( naevner == 0){<br />

67 return null ;<br />

68 }<br />

69<br />

70 // t t i l i n d s æ t t e l s e i l i n j e n s p a r a m e t e r f r e m s t i l l i n g udregnes .<br />

71 double t = − 1 ∗ ((A ∗ o e j e . x + B ∗ o e j e . y + C ∗ o e j e . z + D) / naevner ) ;<br />

72<br />

73 // t j e k k e r om s k æ r i n g s p u n k t e t l i g g e r bag kameraet .<br />

74 i f ( t < 1.0){<br />

75 return null ;<br />

76 }<br />

77<br />

78 // p˚aregner s k a l a r e t p˚a g i t t e r v e k t o r e n<br />

79 Vektor skalarAfV = Vektor . s k a l e r ( g i t t e r v e k t o r , t ) ;<br />

80<br />

81 // udregner og r e t u r n e r e s k æ r i n g s p u n k t e t .<br />

82 return Vektor . t i l P u n k t ( Vektor . adder ( Vektor . lavVektor ( o e j e ) , skalarAfV ) ) ;<br />

83 }<br />

84<br />

85 public Vektor findNormalvektor ( Punkt skaeringspunkt , Punkt o e j e ){<br />

86 /∗ udregner om normalvektoren s k a l vendes om, afhængigt a f h v i l k e n<br />

87 ∗ en a f dem som peger imod ø j e t .<br />

88 ∗<br />

89 ∗ udregner den f ø r s t e a f s t a n d s v e k t o r ved at l a v e en v e k t o r mellem ø j e t<br />

90 ∗ og p l a n e t s skæringspunkt sammenlagt med normalvektoren .<br />

91 ∗/<br />

92 Vektor a f s t a n d s v e k t o r 1 = Vektor . lavVektor ( oeje ,<br />

93 Vektor . t i l P u n k t ( Vektor . adder ( Vektor . lavVektor ( skaeringspunkt ) ,<br />

94 normalvektor ) ) ) ;<br />

95<br />

96 // udregner den anden a f s t a n d s v e k t o r ved samme udregning som før , b o r t<br />

97 // s e t f r a at normalvektoren er i n v e r t e r e t .<br />

98 Vektor a f s t a n d s v e k t o r 2 = Vektor . lavVektor ( oeje ,<br />

99 Vektor . t i l P u n k t ( Vektor . adder ( Vektor . lavVektor ( skaeringspunkt ) ,<br />

100 Vektor . vend ( normalvektor ) ) ) ) ;<br />

101<br />

102 // r e t u r n e r e den v e k t o r som har den k o r t e s t e a f s t a n d t i l ø j e t .<br />

103 i f ( Vektor . laengde ( a f s t a n d s v e k t o r 1 ) < Vektor . laengde ( a f s t a n d s v e k t o r 2 ) ) {<br />

91


104 return normalvektor ;<br />

105 }<br />

106 else {<br />

107 return Vektor . vend ( normalvektor ) ;<br />

108 }<br />

109 }<br />

110 }<br />

92


E.9 Punkt.java<br />

0 class Punkt {<br />

1 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

2 Punkt . java<br />

3<br />

4 Punkt ( double x , double y , double z )<br />

5<br />

6 Constructor der o p r e t t e r e t punkt i det 3− dimesionale plan .<br />

7<br />

8 Koordinaterne er f i n a l da de i k k e s k a l ændres .<br />

9<br />

10 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

11<br />

12 // f i e l d s<br />

13 public f i n a l double x ;<br />

14 public f i n a l double y ;<br />

15 public f i n a l double z ;<br />

16<br />

17 // c o n s t r u c t o r s<br />

18 public Punkt ( double x , double y , double z ) {<br />

19 this . x = x ;<br />

20 this . y = y ;<br />

21 this . z = z ;<br />

22 }<br />

23 }<br />

93


E.10 Scene.java<br />

0 import java . awt . Color ;<br />

1<br />

2 public class Scene {<br />

3 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

4 Scene . java<br />

5<br />

6 Scene ( Figur [ ] f i g u r e r , Sol s o l )<br />

7<br />

8 Constructor som i n s t a n c i e r e Scenen , hvor f i g u r e r er a l l e f i g u r e r som<br />

9 forekommer i scenen og s o l er den s o l som s k a l være i scenen .<br />

10<br />

11 Color nuance ( Punkt oeje , Vektor g i t t e r v e k t o r )<br />

12<br />

13 udregner nuancen i punktet f o r den f i g u r som den l i n j e der b l i v e r u d g j o r t a f<br />

14 o e j e og g i t t e r v e k t o r rammer f ø r s t , hvor g i t t e r v e k t o r s s k a l a r i k k e m˚a være<br />

15 mindre end 1 , og hvor det gælder at s o l e n ogs˚a s k a l ramme punktet .<br />

16<br />

17 o p f y l d e s det i k k e at g i t t e r v e k t o r s s k a l a r er mindre end 1 , da r e t u r n e r e s<br />

18 farven f o r den næste f i g u r som rammes , hvor det gælder at g i t t e r v e k t o r s<br />

19 s k a l a r er < 1;<br />

20<br />

21 rammer s o l e n i k k e punktet , da er punktet i skygge , og en s o r t r e t u r n e r e s .<br />

22<br />

23 rammes ingen f i g u r e r f r a scenen overhovedet , da r e t u r n e r e s s o r t .<br />

24<br />

25 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

26 // F i e l d s<br />

27 private Figur [ ] f i g u r e r ;<br />

28 private Sol s o l ;<br />

29<br />

30 // Constructors<br />

31 public Scene ( Figur [ ] f i g u r e r , Sol s o l ){<br />

32 this . f i g u r e r = f i g u r e r ;<br />

33 this . s o l = s o l ;<br />

34 }<br />

35 // Methods<br />

36 public Color nuance ( Punkt oeje , Vektor g i t t e r v e k t o r ){<br />

37 Punkt skaeringspunkt = null ;<br />

38 int f i g u r = −1;<br />

39 // f i n d e r s k æ r i n g s p u n k t e t og den f i g u r som er nærmest ø j e t ved den givne<br />

40 // v e k t o r .<br />

41 {<br />

42 double afstand = −1;<br />

43<br />

44 for ( int i = 0 ; i < f i g u r e r . length ; i ++){<br />

45 // punktet der rammes p˚a f i g u r nummer i<br />

46 Punkt skpunkt = f i g u r e r [ i ] . skaeringspunkt ( g i t t e r v e k t o r , o e j e ) ;<br />

47<br />

48 i f ( skpunkt ! = null ){<br />

49 double temp = Vektor . laengde ( Vektor . lavVektor ( oeje , skpunkt ) ) ;<br />

50<br />

94


51 // den f ø r s t e f i g u r som b l i v e r ramt .<br />

52 i f ( afstand == −1){<br />

53 afstand = temp ;<br />

54 f i g u r = i ;<br />

55 skaeringspunkt = skpunkt ;<br />

56 }<br />

57<br />

58 // h v i s denne f i g u r er t æ t t e r e p˚a ø j e t end den h i d t i l .<br />

59 i f ( temp < afstand ){<br />

60 afstand = temp ;<br />

61 f i g u r = i ;<br />

62 skaeringspunkt = skpunkt ;<br />

63 }<br />

64 }<br />

65 }<br />

66<br />

67 // har i k k e ramt nogen f i g u r e r .<br />

68 i f ( f i g u r == −1)<br />

69 return Color . black ;<br />

70 }<br />

71 // t j e k k e r om det fundne skæringspunkt ogs˚a b l i v e r ramt a f s o l e n<br />

72 {<br />

73 // udregner vektoren mellem s o l e n og s k æ r i n g s p u n k t e t<br />

74 Vektor solTilSkpunkt = Vektor . lavVektor ( s o l . p o s i t i o n ,<br />

75 skaeringspunkt ) ;<br />

76<br />

77 // s k a l e r e v e k t o r e r e n ned , s˚a l e d e s t i l længde 1 , f o r at f o r at undg˚a<br />

78 // t < 1 ved udregning a f skæringspunkt mellem s o l og f i g u r .<br />

79 solTilSkpunkt = Vektor . s k a l e r ( solTilSkpunkt , 1 . 0 /<br />

80 Vektor . laengde ( solTilSkpunkt ) ) ;<br />

81<br />

82 double afstand = −1;<br />

83 Punkt naermestePunkt = null ;<br />

84<br />

85 for ( int i = 0 ; i < f i g u r e r . length ; i ++){<br />

86 // punktet p˚a f i g u r nummer i som b l i v e r ramt a f s o l e n med<br />

87 // r e t n i n g mod s k æ r i n g s p u n k t e t f r a ø j e t .<br />

88 Punkt solpunkt = f i g u r e r [ i ] . skaeringspunkt ( solTilSkpunkt ,<br />

89 s o l . p o s i t i o n ) ;<br />

90<br />

91 i f ( solpunkt ! = null ){<br />

92 double temp = Vektor . laengde ( Vektor . lavVektor ( s o l . p o s i t i o n ,<br />

93 solpunkt ) ) ;<br />

94<br />

95 // den f ø r s t e f i g u r s o l e n rammer .<br />

96 i f ( afstand == −1){<br />

97 afstand = temp ;<br />

98 naermestePunkt = solpunkt ;<br />

99 }<br />

100<br />

101 // denne f i g u r er t æ t t e r e p˚a s o l e n end den h i d t i l .<br />

102 i f ( temp < afstand ){<br />

103 afstand = temp ;<br />

95


104 naermestePunkt = solpunkt ;<br />

105 }<br />

106 }<br />

107 }<br />

108<br />

109 // har s o l e n overhovedet i k k e ramt nogen f i g u r .<br />

110 i f ( naermestePunkt == null ){<br />

111 throw new RuntimeException ( ” Solen ramte ikke det ”+<br />

112 ”samme punkt som o e j e t ” ) ;<br />

113 }<br />

114<br />

115 // det nærmeste punkt s o l e n rammer er i k k e det samme som s k æ r i n g s p u n k t e t .<br />

116 double f o r s k e l = Vektor . laengde (<br />

117 Vektor . lavVektor ( naermestePunkt , skaeringspunkt ) ) ;<br />

118<br />

119 // u n ø j a g t i g h e d e n mellem de to punkter er her v a l g t t i l maksimalt at m˚a<br />

120 // være 0 . 0 0 0 0 0 1 , e l l e r s k o n s t a t e r e s det at s o l e n i k k e har ramt punktet .<br />

121 i f ( f o r s k e l > 0.000001){<br />

122 return Color . black ;<br />

123 }<br />

124 }<br />

125<br />

126 // s o l e n rammer a l t s˚a f i g u r e n , h v i l k e t gør at nuancen s k a l udregnes .<br />

127 return f i g u r e r [ f i g u r ] . nuance ( skaeringspunkt , oeje , s o l ) ;<br />

128 }<br />

129 }<br />

96


E.11 Sol.java<br />

0 import java . awt . Color ;<br />

1<br />

2 public class Sol {<br />

3 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

4 Sol . java<br />

5<br />

6 Sol ( Punkt p o s i t i o n , Color f a r v e )<br />

7<br />

8 Constructor der o p r e t t e r en l y s k i l d e i p o s i t i o n med l y s i n t e n s i t e t f a r v e<br />

9<br />

10 p o s i t i o n og f a r v e er f i n a l da de i k k e s k a l ændres<br />

11<br />

12 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

13<br />

14 // f i e l d s<br />

15 public f i n a l Punkt p o s i t i o n ;<br />

16 public f i n a l Color f a r v e ;<br />

17<br />

18 // c o n s t r u c t o r s<br />

19 public Sol ( Punkt p o s i t i o n , Color f a r v e ){<br />

20 this . p o s i t i o n = p o s i t i o n ;<br />

21 this . f a r v e = f a r v e ;<br />

22 }<br />

23 }<br />

97


E.12 Stoerrelsesfejl.java<br />

0 class S t o e r r e l s e s f e j l extends IndexOutOfBoundsException {<br />

1 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

2 S t o e r r e l s e s f e j l . java<br />

3<br />

4 S t o e r r e l s e s f e j l ( S t r i n g s )<br />

5 Constructor . s er f e j l b e s k e d e n .<br />

6<br />

7 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

8 S t o e r r e l s e s f e j l ( S t r i n g s )<br />

9 { super ( s ) ; }<br />

10 }<br />

98


E.13 Trekant.java<br />

0 import java . awt . Color ;<br />

1 // i n d b y g g e t Point o b j e k t som kan h˚andtere double .<br />

2 import java . awt . geom . Point2D . Double ;<br />

3<br />

4 public class Trekant extends Figur {<br />

5 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

6 Trekant . java<br />

7<br />

8 Trekant ( Punkt a , Punkt b , Punkt c , Color f a r v e )<br />

9<br />

10 Constructor som kun k a l d e r den anden c o n s t r u c t o r .<br />

11 Ud over at den sender a l l e argumenter videre , s˚a sender den ogs˚a<br />

12 s t a t i c v a r i a b l e n ” r e f l e k t i o n s k o e f f i c i e n t D e f a u l t ” f r a Figur k l a s s e n med .<br />

13<br />

14 Trekant ( Punkt a , Punkt b , Punkt c , Color f a r v e )<br />

15<br />

16 Constructor som i n s t a n c i e r e s i n s u p e r k l a s s e , og s æ t t e r a , b og c t i l<br />

17 punkt 1 , punkt 2 og punkt 3 .<br />

18 Desuden o p r e t t e r den det plan som t r e k a n t e n l i g g e r i , og gemmer i<br />

19 v a r i a b l e n plan .<br />

20<br />

21 Punkt s k a e r i n g s p u n k t ( Vektor g i t t e r v e k t o r , Punkt o e j e )<br />

22<br />

23 r e t u r n e r e s k æ r i n g s p u n k t e t f o r t r e k a n t e n og den l i n j e som g i t t e r v e k t o r<br />

24 og o e j e udgør . f ø r s t t j e k k e s om der er i skæringspunkt mellem t r e k a n t e n s<br />

25 plan og l i n j e n , og d e r e f t e r om det skæringspunkt l i g g e r i t r e k a n t e n .<br />

26<br />

27 Vektor findNormalvektor ( Punkt skaeringspunkt , Punkt o e j e )<br />

28<br />

29 r e t u r n e r e normalvektoren f o r t r e k n t e n s plan som peger imod oeje , hvor o e j e<br />

30 er ø j e t f r a kameraet og s k a e r i n g s p u n k t er s k æ r i n g s p u n k t e t f o r<br />

31 f i g u r e n og den l i n j e som den a k t u e l l e g i t t e r v e k t o r og o e j e udgør .<br />

32<br />

33 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

34 // F i e l d s<br />

35 private f i n a l double r e f l e k t i o n s k o e f f i c i e n t D e f a u l t = 1 . 0 ;<br />

36<br />

37 private f i n a l Punkt punkt1 ;<br />

38 private f i n a l Punkt punkt2 ;<br />

39 private f i n a l Punkt punkt3 ;<br />

40<br />

41 private f i n a l Plan plan ;<br />

42 // Constructors<br />

43 public Trekant ( Punkt a , Punkt b , Punkt c , Color f a r v e ){<br />

44 this ( a , b , c , farve , Figur . r e f l e k t i o n s k o e f f i c i e n t D e f a u l t ) ;<br />

45 }<br />

46<br />

47 public Trekant ( Punkt a , Punkt b , Punkt c , Color farve ,<br />

48 double r e f l e k t i o n s k o e f f i c i e n t ){<br />

49 super ( farve , r e f l e k t i o n s k o e f f i c i e n t ) ;<br />

50<br />

99


51 punkt1 = a ;<br />

52 punkt2 = b ;<br />

53 punkt3 = c ;<br />

54<br />

55 plan = new Plan ( punkt1 , Vektor . lavVektor ( punkt1 , punkt2 ) ,<br />

56 Vektor . lavVektor ( punkt1 , punkt3 ) , f a r v e ) ;<br />

57 }<br />

58 // Methods<br />

59 public Punkt skaeringspunkt ( Vektor v , Punkt p){<br />

60 Punkt skaeringspunkt = plan . skaeringspunkt ( v , p ) ;<br />

61<br />

62 // t j e k k e r om punktet l i g g e r i den plan som t r e k a n t e n udspænder ,<br />

63 i f ( skaeringspunkt ! = null ){<br />

64 // p r o j i c e r e t r e k a n t e n ned p˚a de t r e grundplaner<br />

65 // X, Y p l a n e t<br />

66 Double XYPlanPunkt1 = new Double ( punkt1 . x , punkt1 . y ) ;<br />

67 Double XYPlanPunkt2 = new Double ( punkt2 . x , punkt2 . y ) ;<br />

68 Double XYPlanPunkt3 = new Double ( punkt3 . x , punkt3 . y ) ;<br />

69<br />

70 // Z , X p l a n e t<br />

71 Double ZXPlanPunkt1 = new Double ( punkt1 . z , punkt1 . x ) ;<br />

72 Double ZXPlanPunkt2 = new Double ( punkt2 . z , punkt2 . x ) ;<br />

73 Double ZXPlanPunkt3 = new Double ( punkt3 . z , punkt3 . x ) ;<br />

74<br />

75 // Z , Y p l a n e t<br />

76 Double ZYPlanPunkt1 = new Double ( punkt1 . z , punkt1 . y ) ;<br />

77 Double ZYPlanPunkt2 = new Double ( punkt2 . z , punkt2 . y ) ;<br />

78 Double ZYPlanPunkt3 = new Double ( punkt3 . z , punkt3 . y ) ;<br />

79<br />

80 // f i n d e r a r e a l e r n e a f p r o j e k t i o n e r n e p˚a grundplanerne .<br />

81 double arealXY = 0 . 5 ∗ a r e a l ( XYPlanPunkt1 , XYPlanPunkt2 , XYPlanPunkt3 ) ;<br />

82 double arealZX = 0 . 5 ∗ a r e a l ( ZXPlanPunkt1 , ZXPlanPunkt2 , ZXPlanPunkt3 ) ;<br />

83 double arealZY = 0 . 5 ∗ a r e a l ( ZYPlanPunkt1 , ZYPlanPunkt2 , ZYPlanPunkt3 ) ;<br />

84<br />

85 // t j e k k e r om arealXY er s t ø r s t<br />

86 i f ( arealXY >= arealZX && arealXY >= arealZY ){<br />

87 i f ( f i n d e s I T r e k a n t ( XYPlanPunkt1 , XYPlanPunkt2 , XYPlanPunkt3 ,<br />

88 new Double ( skaeringspunkt . x , skaeringspunkt . y ) ) ) {<br />

89 return skaeringspunkt ;<br />

90 }<br />

91 else{<br />

92 // punktet b e f a n d t s i g i k k e inde i t r e k a n t e n .<br />

93 return null ;<br />

94 }<br />

95 }<br />

96 // t j e k k e r om arealZX er s t ø r s t<br />

97 i f ( arealZX >= arealXY && arealZX >= arealZY ){<br />

98 i f ( f i n d e s I T r e k a n t ( ZXPlanPunkt1 , ZXPlanPunkt2 , ZXPlanPunkt3 ,<br />

99 new Double ( skaeringspunkt . z , skaeringspunkt . x ) ) ) {<br />

100 return skaeringspunkt ;<br />

101 }<br />

102 else{<br />

103 // punktet b e f a n d t s i g i k k e inde i t r e k a n t e n .<br />

100


104 return null ;<br />

105 }<br />

106 }<br />

107<br />

108 // arealZY m˚a være det s t ø r s t e , og udfra d e t t e t j e k k e s om punktet<br />

109 // l i g g e r i t r e k a n t e n .<br />

110 i f ( f i n d e s I T r e k a n t ( ZYPlanPunkt1 , ZYPlanPunkt2 , ZYPlanPunkt3 ,<br />

111 new Double ( skaeringspunkt . z , skaeringspunkt . y ) ) ) {<br />

112 return skaeringspunkt ;<br />

113 }<br />

114 else {<br />

115 // punktet b e f a n d t s i g i k k e inde i t r e k a n t e n .<br />

116 return null ;<br />

117 }<br />

118 }<br />

119 else {<br />

120 // l i n j e n skær i k k e t r e k a n t e n s plan<br />

121 return null ;<br />

122 }<br />

123 }<br />

124<br />

125 private boolean f i n d e s I T r e k a n t ( Double p1 , Double p2 , Double p3 , Double q ){<br />

126 // udregner determinanter<br />

127 double determinantSide1 =<br />

128 ( q . getX () − p1 . getX ( ) ) ∗ ( p2 . getY () − p1 . getY ()) −<br />

129 ( q . getY () − p1 . getY ( ) ) ∗ ( p2 . getX () − p1 . getX ( ) ) ;<br />

130<br />

131 double determinantSide2 =<br />

132 ( q . getX () − p2 . getX ( ) ) ∗ ( p3 . getY () − p2 . getY ()) −<br />

133 ( q . getY () − p2 . getY ( ) ) ∗ ( p3 . getX () − p2 . getX ( ) ) ;<br />

134<br />

135 double determinantSide3 =<br />

136 ( q . getX () − p3 . getX ( ) ) ∗ ( p1 . getY () − p3 . getY ()) −<br />

137 ( q . getY () − p3 . getY ( ) ) ∗ ( p1 . getX () − p3 . getX ( ) ) ;<br />

138<br />

139 return<br />

140 ( ( determinantSide1 >= 0 && determinantSide2 >= 0 && determinantSide3 > = 0 ) | |<br />

141 ( determinantSide1


157 public Vektor findNormalvektor ( Punkt p , Punkt o e j e ){<br />

158 return plan . findNormalvektor (p , o e j e ) ;<br />

159 }<br />

160 }<br />

102


E.14 Vektor.java<br />

0 class Vektor {<br />

1 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

2 Vektor . java<br />

3<br />

4 Vektor ( double x , double y , double z )<br />

5 Contructor der l a v e r en v e k t o r<br />

6<br />

7 x , y og z er a l l e s t a t i c da de i k k e s k a l ændres .<br />

8<br />

9 s t a t i c Vektor lavVektor ( Punkt p1 )<br />

10 Laver v e k t o r f r a 1 punkt<br />

11<br />

12 s t a t i c Punkt t i l P u n k t ( Vektor v1 )<br />

13 Laver en v e k t o r om t i l e t Punkt<br />

14<br />

15 s t a t i c Vektor vend ( Vektor v1 )<br />

16 I n v e r t e r e r en v e k t o r<br />

17<br />

18 s t a t i c double laengde ( Vektor v1 )<br />

19 Udregner længden a f en v e k t o r ( Opgaveformulering B. 3 . 1 )<br />

20<br />

21 s t a t i c Vektor s k a l e r ( Vektor v1 , double s k a l a r )<br />

22 M u l t i p l i c e r e r en v e k t o r med en s k a l a r ( Opgaveformulering B. 3 . 3 )<br />

23<br />

24 s t a t i c Vektor adder ( Vektor v1 , Vektor v2 )<br />

25 Adderer 2 v e k t o r e r ( Opgaveformulering B. 3 . 4 )<br />

26<br />

27 s t a t i c Vektor s u b t r a h e r ( Vektor v1 , Vektor v2 )<br />

28 Subtraherer 2 v e k t o r e r f r a hinanden ( Opgaveformuleringen B. 3 . 4 )<br />

29<br />

30 s t a t i c double s k a l a r p r o d u k t ( Vektor v1 , Vektor v2 )<br />

31 Udregner s k a l a r p r o d u k t e t a f 2 v e k t o r e r ( Opgaveformulering B. 3 . 6 )<br />

32<br />

33 s t a t i c Vektor lavVektor ( Punkt p1 , Punkt p2 )<br />

34 Laver en v e k t o r udfra 2 punkter ( Opgaveformuleringen B. 3 . 7 )<br />

35<br />

36 s t a t i c Vektor krydsprodukt ( Vektor v1 , Vektor v2 )<br />

37 Udregner k r y d s p r o d u k t e t f o r 2 v e k t o r e r ( Opgaveformuleringen B. 3 . 8 )<br />

38<br />

39 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

40 // f i e l d s<br />

41 public f i n a l double x ;<br />

42 public f i n a l double y ;<br />

43 public f i n a l double z ;<br />

44<br />

45 // c o n s t r u c t o r<br />

46 public Vektor ( double x , double y , double z ) {<br />

47 this . x = x ;<br />

48 this . y = y ;<br />

49 this . z = z ;<br />

50 }<br />

103


51<br />

52 // methods<br />

53 public static Vektor lavVektor ( Punkt p1 ) {<br />

54 return new Vektor ( p1 . x , p1 . y , p1 . z ) ;<br />

55 }<br />

56<br />

57 public static Punkt t i l P u n k t ( Vektor v1 ) {<br />

58 return new Punkt ( v1 . x , v1 . y , v1 . z ) ;<br />

59 }<br />

60<br />

61 public static Vektor vend ( Vektor v1 ) {<br />

62 return new Vektor(−v1 . x,−v1 . y,−v1 . z ) ;<br />

63 }<br />

64<br />

65 public static double laengde ( Vektor v1 ) {<br />

66 return Math . s q r t (Math . pow( v1 . x ,2)+<br />

67 Math . pow( v1 . y ,2)+Math . pow( v1 . z , 2 ) ) ;<br />

68 }<br />

69<br />

70 public static Vektor s k a l e r ( Vektor v1 , double s k a l a r ) {<br />

71 return new Vektor ( v1 . x∗ skalar , v1 . y∗ skalar , v1 . z∗ s k a l a r ) ;<br />

72 }<br />

73<br />

74 public static Vektor adder ( Vektor v1 , Vektor v2 ) {<br />

75 return new Vektor ( v1 . x+v2 . x , v1 . y+v2 . y , v1 . z+v2 . z ) ;<br />

76 }<br />

77<br />

78 public static Vektor subtraher ( Vektor v1 , Vektor v2 ) {<br />

79 return new Vektor ( v1 . x−v2 . x , v1 . y−v2 . y , v1 . z−v2 . z ) ;<br />

80 }<br />

81<br />

82 public static double skalarprodukt ( Vektor v1 , Vektor v2 ) {<br />

83 return v1 . x∗v2 . x+v1 . y∗v2 . y+v1 . z ∗v2 . z ;<br />

84 }<br />

85<br />

86 public static Vektor lavVektor ( Punkt p1 , Punkt p2 ) {<br />

87 return new Vektor ( p2 . x − p1 . x , p2 . y−p1 . y , p2 . z−p1 . z ) ;<br />

88 }<br />

89<br />

90 public static Vektor krydsprodukt ( Vektor v1 , Vektor v2 ) {<br />

91 return new Vektor ( v1 . y∗v2 . z−v1 . z ∗v2 . y ,<br />

92 v1 . z ∗v2 . x−v1 . x∗v2 . z ,<br />

93 v1 . x∗v2 . y−v1 . y∗v2 . x ) ;<br />

94 }<br />

95 }<br />

104


E.15 XMLParseError.java<br />

0 public class XMLParseError extends Throwable{<br />

1 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

2 XMLParseError . java<br />

3<br />

4 XMLParseError( S t r i n g s )<br />

5<br />

6 Konstruerer e t XMLParseError o b j e k t . s er f e j l b e s k e d e n .<br />

7<br />

8 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

9 XMLParseError ( S t r i n g s ){ super ( s ) ; }<br />

10 }<br />

105


E.16 XMLParser.java<br />

0 import java . awt . Color ;<br />

1 // t i l opbygning a f xml<br />

2 import javax . xml . p a r s e r s . DocumentBuilder ;<br />

3 import javax . xml . p a r s e r s . DocumentBuilderFactory ;<br />

4 import javax . xml . p a r s e r s . FactoryConfigurationError ;<br />

5 import javax . xml . p a r s e r s . ParserConfigurationException ;<br />

6 import org . xml . sax . SAXException ;<br />

7 import org . xml . sax . SAXParseException ;<br />

8 // t i l l o a d i n g a f xml f i l e n , p l u s e x c e p t i o n<br />

9 import java . i o . F i l e ;<br />

10 import java . i o . IOException ;<br />

11 import java . u t i l . ∗ ;<br />

12 import java . lang . Double ; // Double . parseDouble<br />

13 import java . lang . I n t e g e r ; // I n t e g e r . p a r s e I n t<br />

14 import org . w3c . dom . ∗ ; // NodeList , Document , Node , Element , e t c .<br />

15<br />

16 public class XMLParser<br />

17 {<br />

18 /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗<br />

19 XMLParser . java<br />

20<br />

21 XMLParser( S t r i n g XMLSti)<br />

22<br />

23 Opretter XML o b j e k t et , henter en XML f i l ind , v i a f i l n a v n e t XMLSti ,<br />

24 udtrækker , og o p r e t t e r a l l e kamera og scene elementer .<br />

25<br />

26 KameraVinkler hentKameraVinkler ( )<br />

27<br />

28 r e t u r n e r e det opbyggede KameraVinkler o b j e k t .<br />

29<br />

30 Scene hentScene ( )<br />

31<br />

32 r e t u r n e r e det opbyggede Scene o b j e k t .<br />

33<br />

34 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/<br />

35 // f i e l d s<br />

36 private Figur [ ] f i g u r ;<br />

37 private Kamera [ ] kamera ;<br />

38 private Sol s o l ;<br />

39<br />

40 // array t i l f i l n a v n e , f o r at checke at de a l l e er f o r s k e l l i g e<br />

41 private S t r i n g f i l n a v n e [ ] ;<br />

42<br />

43 // constructor , der er kun en . der k a s t e s kun IO e l l e r XML e x c e p t i o n s<br />

44 public XMLParser( S t r i n g XMLSti ) throws XMLParseError , IOException {<br />

45 NodeList nl ; // g e n e r a l node l i s t h o l d e r<br />

46 Node [ ] n l a r r ; // g e n e r a l node array , s u b s t f o r n o d e l i s t .<br />

47 Node [ ] nlarrMesh ;<br />

48 Node [ ] nlarrKugle ;<br />

49 Node [ ] n l a r r P l a n ;<br />

50 Element root = null ; // document root h o l d e r<br />

106


51<br />

52 // her l o a d e s documentet .<br />

53 try {<br />

54 DocumentBuilderFactory f a c t o r y = DocumentBuilderFactory . newInstance ( ) ;<br />

55 DocumentBuilder b u i l d e r = f a c t o r y . newDocumentBuilder ( ) ;<br />

56 root=b u i l d e r . parse ( new F i l e (XMLSti ) ) . getDocumentElement ( ) ;<br />

57 } catch ( SAXException sxe ) {<br />

58 throw new XMLParseError ( ” I n v a l i d XML format : ” + sxe . getMessage ( ) ) ;<br />

59 } catch ( ParserConfigurationException pce ) {<br />

60 pce . printStackTrace ( ) ; // l a d os h˚abe det her i k k e kommer .<br />

61 } catch ( IOException i o e ) {<br />

62 throw new IOException ( ” F e j l i f i l s y s t e m : ” + i o e . getMessage ( ) ) ;<br />

63 }<br />

64<br />

65 i f ( ! root . getNodeName ( ) . e q u a l s ( ” scene ” ) ) {<br />

66 throw new XMLParseError ( ”Rod−element s k a l være a f type ” ) ;<br />

67 }<br />

68 // ////////////////////////////////////////////////////////////////////<br />

69 // ////////////////////////////////////////////////////////////////////<br />

70 // opbyg KameraVinkler<br />

71 n l a r r = findElementer ( root , ” p i l o t s y n ” ) ;<br />

72 i f ( n l a r r . length < 1) {<br />

73 throw new XMLParseError ( ”Der kræves mindst et p i l o t s y n . ” ) ;<br />

74 }<br />

75 kamera = new Kamera [ n l a r r . length ] ;<br />

76 f i l n a v n e = new S t r i n g [ n l a r r . length ] ;<br />

77<br />

78 for ( int i = 0 ; i < n l a r r . length ; i ++){<br />

79 kamera [ i ] = lavKamera ( n l a r r [ i ] , i ) ;<br />

80 }<br />

81 // l a v sol , findElement s ø r g e r f o r kun en < s o l /><br />

82 s o l = l a v S o l ( findElement ( root , ” s o l ” ) ) ;<br />

83 // ////////////////////////////////////////////////////////////////////<br />

84 // ////////////////////////////////////////////////////////////////////<br />

85 // v i f i n d e r l i g e ud a f hvor s t o r f i g u r [ ] s k a l værer<br />

86 nlarrMesh = findElementer ( root , ”mesh” ) ;<br />

87 nlarrKugle = findElementer ( root , ” kugle ” ) ;<br />

88 n l a r r P l a n = findElementer ( root , ” plan ” ) ;<br />

89 int a n t a l F i g u r e r = nlarrMesh . length + nlarrKugle . length + n l a r r P l a n . length ;<br />

90<br />

91 f i g u r = new Figur [ a n t a l F i g u r e r ] ;<br />

92 // l a v f i g u r e<br />

93 nl = root . getChildNodes ( ) ;<br />

94 int j = 0 ;<br />

95 for ( int i = 0 ; i < nlarrMesh . length ; i ++) {<br />

96 f i g u r [ j ++] = lavMesh ( nlarrMesh [ i ] ) ;<br />

97 }<br />

98<br />

99 for ( int i = 0 ; i < nlarrKugle . length ; i ++) {<br />

100 f i g u r [ j ++] = lavKugle ( nlarrKugle [ i ] ) ;<br />

101 }<br />

102<br />

103 for ( int i = 0 ; i < n l a r r P l a n . length ; i ++) {<br />

107


104 f i g u r [ j ++] = lavPlan ( n l a r r P l a n [ i ] ) ;<br />

105 }<br />

106 // c o n s t r u c t o r s l u t<br />

107 }<br />

108<br />

109 // hjælpe f u n k t i o n t i l at have x/y/ z ud a f e t element .<br />

110 private double [ ] punkter ( Node n ) throws XMLParseError{<br />

111 Element elm = ( Element ) n ;<br />

112 double [ ] p = new double [ 3 ] ;<br />

113 try {<br />

114 // x/y/ z s k a l f i n d e s , og have Double format .<br />

115 p [ 0 ] = Double . parseDouble ( elm . g e t A t t r i b u t e ( ”x” ) ) ;<br />

116 p [ 1 ] = Double . parseDouble ( elm . g e t A t t r i b u t e ( ”y” ) ) ;<br />

117 p [ 2 ] = Double . parseDouble ( elm . g e t A t t r i b u t e ( ”z” ) ) ;<br />

118 // de f o r s k e l l i g e e x c e p t i o n s bruges t i l at<br />

119 // a f g ø r e r h v i l k e n f e j l det var<br />

120 } catch ( NumberFormatException exn ) {<br />

121 throw new XMLParseError ( ”’ s x/y/z a t t r i b u t t e r ”+<br />

122 ” var ikke i k o r r e k t format ” ) ;<br />

123 } catch ( RuntimeException exn ) {<br />

124 throw new XMLParseError ( ” manglede x/y/z a t t r i b u t t e n ” ) ;<br />

125 }<br />

126 return p ;<br />

127 }<br />

128<br />

129 private boolean checkTrekant ( Punkt p1 , Vektor v2 , Vektor v3 ) {<br />

130 Punkt p2 = Vektor . t i l P u n k t ( Vektor . adder ( Vektor . lavVektor ( p1 ) , v2 ) ) ;<br />

131 Punkt p3 = Vektor . t i l P u n k t ( Vektor . adder ( Vektor . lavVektor ( p1 ) , v3 ) ) ;<br />

132 return checkTrekant ( p1 , p2 , p3 ) ;<br />

133 }<br />

134<br />

135 private boolean checkTrekant ( Punkt p1 , Punkt p2 , Punkt p3 ) {<br />

136 Vektor a = Vektor . lavVektor ( p1 , p2 ) ;<br />

137 Vektor b = Vektor . lavVektor ( p2 , p3 ) ;<br />

138 Vektor c = Vektor . lavVektor ( p3 , p1 ) ;<br />

139 double aStr = Vektor . laengde ( a ) ;<br />

140 double bStr = Vektor . laengde ( b ) ;<br />

141 double cStr = Vektor . laengde ( c ) ;<br />

142<br />

143 return (<br />

144 ( aStr + bStr ) > cStr &&<br />

145 ( bStr + cStr ) > aStr &&<br />

146 ( cStr + aStr ) > bStr ) ;<br />

147 }<br />

148<br />

149 // hjælpe f u n k t i o n t i l at h i v e RGB ud a f e t < f a r v e/><br />

150 private int [ ] rgbFarver ( Node n ) throws XMLParseError{<br />

151 Element elm = ( Element ) n ;<br />

152 int [ ] p = new int [ 3 ] ;<br />

153 try {<br />

154 p [ 0 ] = I n t e g e r . p a r s e I n t ( elm . g e t A t t r i b u t e ( ” r ” ) ) ;<br />

155 p [ 1 ] = I n t e g e r . p a r s e I n t ( elm . g e t A t t r i b u t e ( ”g” ) ) ;<br />

156 p [ 2 ] = I n t e g e r . p a r s e I n t ( elm . g e t A t t r i b u t e ( ”b” ) ) ;<br />

108


157 } catch ( NumberFormatException exn ) {<br />

158 throw new XMLParseError ( ”’ s r /g/b a t t r i b u t t e r ”+<br />

159 ” var ikke i k o r r e k t format ” ) ;<br />

160 } catch ( RuntimeException exn ) {<br />

161 throw new XMLParseError ( ” manglede r /g/b a t t r i b u t t e n ” ) ;<br />

162 }<br />

163 // rgb værdierne s k a l være i decimal , og inden f o r 0−255<br />

164 i f ( p [ 0 ] > 2 5 5 | | p [ 1 ] > 2 5 5 | | p [ 2 ] > 2 5 5 | |<br />

165 p [ 0 ] < 0 | | p [ 1 ] < 0 | | p [ 2 ] < 0 ) {<br />

166 throw new XMLParseError ( ”’ s r /g/b a t t r i b u t t e r ”+<br />

167 ” var uden f o r 0−255” ) ;<br />

168 }<br />

169 return p ;<br />

170 }<br />

171<br />

172 private Element findElement ( Node n , S t r i n g t ) throws XMLParseError {<br />

173 // m˚a kun f i n d e s e t Element a f type ” t ” i h e l e træet<br />

174 Node [ ] nl = findElementer (n , t ) ;<br />

175 NodeList n l l = ( ( Element ) n ) . getElementsByTagName( t ) ;<br />

176 i f ( nl . length ! = 1 ) {<br />

177 throw new XMLParseError ( ”For f˚a /mange ” ) ;<br />

178 }<br />

179 // c a s t t i l Element , da Element er<br />

180 // umiddelbart mere t i l g æ n g e l i n g<br />

181 Element elm = ( Element ) nl [ 0 ] ;<br />

182 return elm ;<br />

183 }<br />

184<br />

185 // f i n d e r a l l e de noder , som f i n d e s d i r e k t e i n ’ s childNodes l i s t<br />

186 // kan i k k e l i g e f˚a den t i l at l a v e nodeList , s˚a det er bare node [ ] : (<br />

187 private Node [ ] findElementer ( Node n , S t r i n g t ) throws XMLParseError {<br />

188 NodeList nc = n . getChildNodes ( ) ; // n ’ s c h i l d n o d e s<br />

189 Node [ ] nl = new Node [ nc . getLength ( ) ] ;<br />

190 Node [ ] n l f ; // n o d e l i s t f i n a l<br />

191 int antalPunkter = 0 ;<br />

192<br />

193 for ( int i = 0 ; i < nc . getLength ( ) ; i ++) {<br />

194 S t r i n g navn = nc . item ( i ) . getNodeName ( ) ;<br />

195 i f ( navn . e q u a l s ( t ) ) {<br />

196 nl [ antalPunkter ] = nc . item ( i ) ;<br />

197 antalPunkter++;<br />

198 }<br />

199 }<br />

200 n l f = new Node [ antalPunkter ] ;<br />

201 for ( int i = 0 ; i < antalPunkter ; i ++) {<br />

202 n l f [ i ] = nl [ i ] ;<br />

203 }<br />

204 return n l f ;<br />

205 }<br />

206<br />

207 private Kugle lavKugle ( Node n ) throws XMLParseError {<br />

208 double r ; // r a d i u s<br />

209 Punkt c ; // centrum<br />

109


210 Color f a r v e ; // f a r v e<br />

211<br />

212 // f i n d r a d i u s<br />

213 S t r i n g rAttr = findElement ( n , ” r a d i u s ” ) . g e t A t t r i b u t e ( ” r ” ) ;<br />

214 i f ( rAttr == ”” ) {<br />

215 // t r o r det her er godt ?<br />

216 throw new XMLParseError ( ” mangler r a t t r i b u t ” ) ;<br />

217 }<br />

218 try {<br />

219 r = Double . parseDouble ( rAttr ) ;<br />

220 i f ( r


263 double [ ] pkoord = punkter ( nl [ i ] ) ;<br />

264 // her s k a l a l l e s æ t t e s . l ø k k e n kører 3 gange , og<br />

265 // p/v1 / v2 m˚a i k k e s æ t t e s to gange , r e s u l t e r e n d e i<br />

266 // at de a l l e s æ t t e s<br />

267 i f ( navn . e q u a l s ( ” stedpunkt” ) ) {<br />

268 i f ( p == null ) {<br />

269 p = new Punkt ( pkoord [ 0 ] , pkoord [ 1 ] , pkoord [ 2 ] ) ;<br />

270 continue ;<br />

271 }<br />

272 } else i f ( navn . e q u a l s ( ” r e t n i n g s v e k t o r 1 ” ) ) {<br />

273 i f ( v1 == null ) {<br />

274 v1 = new Vektor ( pkoord [ 0 ] , pkoord [ 1 ] , pkoord [ 2 ] ) ;<br />

275 continue ;<br />

276 }<br />

277 } else i f ( navn . e q u a l s ( ” r e t n i n g s v e k t o r 2 ” ) ) {<br />

278 i f ( v2 == null ) {<br />

279 v2 = new Vektor ( pkoord [ 0 ] , pkoord [ 1 ] , pkoord [ 2 ] ) ;<br />

280 continue ;<br />

281 }<br />

282 }<br />

283 // røg i k k e ind i en a f i f t e s t e n e<br />

284 throw new XMLParseError ( ” Forkert id a t t r i b u t i ” ) ;<br />

285 }<br />

286<br />

287 i f ( ! checkTrekant (p , v1 , v2 ) ) {<br />

288 throw new XMLParseError ( ” Vektorer og punktet i ”+<br />

289 ” d e f i n e r e ikke et plan ” ) ;<br />

290 }<br />

291 return new Plan ( p , v1 , v2 , f a r v e ) ;<br />

292 }<br />

293<br />

294 private Mesh lavMesh ( Node n ) throws XMLParseError {<br />

295 Color f a r v e ;<br />

296 Punkt [ ] punkter ; // h o l d e r t i l de mulige t r e k a n t h j ø e r n e r<br />

297 Trekant [ ] t r e k a n t e r ; // h o l d e r t i l de t r e k a n t e r som opbygges<br />

298 NodeList nl ; // g e n e r e l n o d e l i s t<br />

299 Node [ ] n l a r r ;<br />

300 int antalPunkter ;<br />

301 int antalTrekanter ;<br />

302<br />

303 // f i n d f a r v e .<br />

304 Node f = ( Node ) findElement ( n , ” f a r v e ” ) ;<br />

305 int [ ] rgb = rgbFarver ( f ) ;<br />

306 f a r v e = new Color ( rgb [ 0 ] , rgb [ 1 ] , rgb [ 2 ] ) ;<br />

307<br />

308 // f i n d ud a f ” a n t a l p u n k t e r ” a t t r i b u t t e n , og sammenlign a n t a l ” punkt ”<br />

309 Element punkterNode = findElement (n , ” punkter ” ) ;<br />

310 // f i n d e s ” a n t a l p u n k t e r ” ?<br />

311 S t r i n g apAttr = punkterNode . g e t A t t r i b u t e ( ” a n t a l p u n k t e r ” ) ;<br />

312 i f ( apAttr == ”” ) {<br />

313 throw new XMLParseError ( ” mangler a n t a l p u n k t e r a t t r i b u t ” ) ;<br />

314 }<br />

315 try {<br />

111


316 antalPunkter = I n t e g e r . p a r s e I n t ( apAttr ) ;<br />

317 } catch ( RuntimeException exn ) {<br />

318 throw new XMLParseError ( ”’s a n t a l p u n k t e r ”+<br />

319 ” i f o r k e r t format ” ) ;<br />

320 }<br />

321<br />

322 // f i n d a n t a l a f elementer .<br />

323 n l a r r = findElementer ( punkterNode , ”punkt” ) ;<br />

324 // ( ( Element )n ) . getElementsByTagName (” punkt ” ) ;<br />

325 i f ( n l a r r . length ! = antalPunkter ) { // sammenlign<br />

326 throw new XMLParseError ( ” Ikke samstemmende a n t a l ”+<br />

327 ” punkter i ” ) ;<br />

328 }<br />

329<br />

330 // k r e e r punkter array<br />

331 punkter = new Punkt [ antalPunkter ] ;<br />

332 for ( int i = 0 ; i < n l a r r . length ; i ++) {<br />

333 // f i n d i d a t t r i b u t e , brug d e t t e som indgang i punkter [ ] ;<br />

334 try {<br />

335 int j = I n t e g e r . p a r s e I n t ( ( ( Element ) n l a r r [ i ] ) . g e t A t t r i b u t e ( ” id ” ) ) ;<br />

336 i f ( punkter [ j ] == null ) {<br />

337 double [ ] pkoord = punkter ( n l a r r [ i ] ) ;<br />

338 punkter [ j ] = new Punkt ( pkoord [ 0 ] , pkoord [ 1 ] , pkoord [ 2 ] ) ;<br />

339 } else {<br />

340 throw new XMLParseError ( ”Samme punkt d e f i n e r e t to gange” ) ;<br />

341 }<br />

342 // her fanges , h v i s i n t c o n v e r t e r i n g e n i k k e g i k godt<br />

343 // e l l e r h v i s i d a t t r i b u t t e n mangler<br />

344 // e l l e r h v i s i d a t t r i b u t t e n er uden f o r 0 − a n t a l p u n k t e r<br />

345 } catch ( RuntimeException exn ) {<br />

346 throw new XMLParseError ( ” mangler id a t t r i b u t , ”+<br />

347 ” e l l e r i f o r k e r t format ” ) ;<br />

348 }<br />

349 }<br />

350<br />

351 // f i n d ud a f ” a n t a l t r e k a n t e r ” a t t r i b u t t e n ,<br />

352 // og sammenlign a n t a l ” t r e k a n t ”<br />

353 // f i n d e s ” a n t a l p u n k t e r ”?<br />

354 S t r i n g atAttr = findElement ( n , ” t r e k a n t e r ” ) . g e t A t t r i b u t e ( ” a n t a l t r e k a n t e r ” ) ;<br />

355 i f ( atAttr == ”” ) {<br />

356 throw new XMLParseError ( ” mangler ”+<br />

357 ” a n t a l t r e k a n t e r a t t r i b u t ” ) ;<br />

358 }<br />

359 try {<br />

360 antalTrekanter = I n t e g e r . p a r s e I n t ( atAttr ) ;<br />

361 } catch ( RuntimeException exn ) {<br />

362 throw new XMLParseError ( ”’s a n t a l p u n k t e r ”+<br />

363 ” i f o r k e r t format ” ) ;<br />

364 }<br />

365<br />

366 // f i n d a n t a l a f < t r e k a n t /> elementer .<br />

367 nl = ( ( Element ) n ) . getElementsByTagName( ” trekant ” ) ;<br />

368 i f ( nl . getLength ( ) ! = antalTrekanter ) {<br />

112


369 throw new XMLParseError ( ” Ikke samstemmende a n t a l ”+<br />

370 ” t r e k a n t e r i ” ) ;<br />

371 }<br />

372<br />

373 // l a v t r e k a n t e r<br />

374 t r e k a n t e r = new Trekant [ antalTrekanter ] ;<br />

375 for ( int i = 0 ; i < nl . getLength ( ) ; i ++) {<br />

376 // f i n d de t r e t a l , som a f g ø r h v i l k e<br />

377 // punkter udspænder t r e k a n t e n<br />

378 Element elm = ( Element ) nl . item ( i ) ;<br />

379 Punkt p1 , p2 , p3 ;<br />

380 try {<br />

381 p1 = punkter [ I n t e g e r . p a r s e I n t ( elm . g e t A t t r i b u t e ( ”p1” ) ) ] ;<br />

382 p2 = punkter [ I n t e g e r . p a r s e I n t ( elm . g e t A t t r i b u t e ( ”p2” ) ) ] ;<br />

383 p3 = punkter [ I n t e g e r . p a r s e I n t ( elm . g e t A t t r i b u t e ( ”p3” ) ) ] ;<br />

384 } catch ( RuntimeException exn ) {<br />

385 throw new XMLParseError ( ”’ s p1/p2/p3 a t t r i b u t ”+<br />

386 ” mangler / f o r k e r t format ” ) ;<br />

387 }<br />

388 i f ( ! checkTrekant ( p1 , p2 , p3 ) ) {<br />

389 throw new XMLParseError ( ”’ s p1/p2/p3 ”+<br />

390 ” d e f i n e r e ikke en trekant ” ) ;<br />

391 }<br />

392 t r e k a n t e r [ i ] = new Trekant ( p1 , p2 , p3 , f a r v e ) ;<br />

393 }<br />

394 return new Mesh ( trekanter , f a r v e ) ;<br />

395 }<br />

396<br />

397 private Kamera lavKamera ( Node n , int j ) throws XMLParseError {<br />

398 int b = 0 ; // hoejde<br />

399 int h = 0 ; // bredde<br />

400 Vektor l = null ; // c o c k p i t v i n d u e l o d r e t<br />

401 Vektor v = null ; // c o c k p i t v i n d u e v a n d r e t<br />

402 Punkt p = null ; // p i l o t o e j e<br />

403 Punkt s = null ; // c o c k p i t v i n d u e s t e d p u n k t<br />

404 S t r i n g f i l n a v n ; // f i l n a v n , h e n t e t f r a < p i l o t s y n />’ s i d<br />

405 Node [ ] n l a r r ; // g e n e r e l node array<br />

406<br />

407 // v i f i n d e r og checker højde og bredde<br />

408 Element elm = ( Element ) n ;<br />

409 try {<br />

410 h = I n t e g e r . p a r s e I n t ( elm . g e t A t t r i b u t e ( ” hoejde ” ) ) ;<br />

411 b = I n t e g e r . p a r s e I n t ( elm . g e t A t t r i b u t e ( ” bredde ” ) ) ;<br />

412 } catch ( NumberFormatException exn ) {<br />

413 throw new XMLParseError ( ”’s hoejde / bredde ”+<br />

414 ” ikke i k o r r e k t format ” ) ;<br />

415 } catch ( RuntimeException exn ) {<br />

416 throw new XMLParseError ( ” mangler ”+<br />

417 ” bredde e l l e r hoejde ” ) ;<br />

418 }<br />

419 i f ( h < 1 | | b < 1) {<br />

420 throw new XMLParseError ( ”’s hoejde / bredde ”+<br />

421 ” s k a l være p o s i t i v e ” ) ;<br />

113


422 }<br />

423<br />

424 // v i f i n d e r f i l n a v n<br />

425 try {<br />

426 f i l n a v n = elm . g e t A t t r i b u t e ( ” id ” ) ;<br />

427 // v i s ø r g e r f o r at f i l n a v n / i d er u n i k t<br />

428 for ( int i = 0 ; i < f i l n a v n e . length ; i ++) {<br />

429 i f ( f i l n a v n e [ i ] == null ) {<br />

430 f i l n a v n e [ i ] = f i l n a v n ;<br />

431 break ;<br />

432 } else i f ( f i l n a v n e [ i ] . e q u a l s ( f i l n a v n ) ) {<br />

433 throw new XMLParseError ( ” mangler ”+<br />

434 ” unik id a t t r i b u t ” ) ;<br />

435 }<br />

436 }<br />

437 } catch ( RuntimeException exn ) {<br />

438 throw new XMLParseError ( ” mangler id a t t r i b u t ” ) ;<br />

439 }<br />

440<br />

441 n l a r r = findElementer ( n , ”punkt” ) ;<br />

442 i f ( n l a r r . length ! = 4 ) {<br />

443 // der s k a l være f i r e elementer<br />

444 throw new XMLParseError ( ”Mangler i < p i l o t s y n />.” ) ;<br />

445 }<br />

446<br />

447 for ( int i =0; i


475 continue ;<br />

476 }<br />

477 }<br />

478 throw new XMLParseError ( ” Forkert id a t t r i b u t i ” ) ;<br />

479 }<br />

480 // check f o r at se , om f i l m e n d e f i n e r e e t plan . e l l e r s f o r k a s t .<br />

481 i f ( ! checkTrekant ( s , l , v ) ) {<br />

482 throw new XMLParseError ( ” d e f i n e r e ikke ”+<br />

483 ” et plan f o r vinduet ” ) ;<br />

484 }<br />

485 return new Kamera(p , s , l , v , h , b , f i l n a v n ) ;<br />

486 }<br />

487<br />

488 private Sol l a v S o l ( Node n ) throws XMLParseError{<br />

489 Color c ;<br />

490 Punkt p ;<br />

491<br />

492 // f i n d f a r v e element<br />

493 Node f = ( Node ) findElement ( n , ” f a r v e ” ) ;<br />

494 int [ ] rgb = rgbFarver ( f ) ;<br />

495 c = new Color ( rgb [ 0 ] , rgb [ 1 ] , rgb [ 2 ] ) ;<br />

496<br />

497 // f i n d p o s i t i o n f o r s o l<br />

498 double [ ] pkoord = punkter ( findElement ( n , ”punkt” ) ) ;<br />

499 p = new Punkt ( pkoord [ 0 ] , pkoord [ 1 ] , pkoord [ 2 ] ) ;<br />

500 return new Sol (p , c ) ;<br />

501 }<br />

502<br />

503 public Scene hentScene ( ) {<br />

504 return new Scene ( f i g u r , s o l ) ;<br />

505 }<br />

506<br />

507 public KameraVinkler hentKameraVinkler ( ) {<br />

508 return new KameraVinkler( kamera ) ;<br />

509 }<br />

510 }<br />

115


Litteratur<br />

[1] Eric Jul. Erics kogebog. http://www.diku.dk/undervisning/2003f/dat0gb/kogebog.html.<br />

[2] Eric Jul. Diku flight simulator <strong>2004</strong>. Technical report, <strong>Datalogi</strong>sk Institut, København<br />

Universitet, 2003. <strong>Datalogi</strong> <strong>0GB</strong>: K-opgave.<br />

[3] James E. Rumbaugh. Modeling models and viewing views: A look at the model-viewcontroller<br />

framework. JOOP 7(2), pages 14–20, 1994.<br />

[4] Søren Sjørup. Pilotsyn. http://www.diku.dk/undervisning/2003f/dat0gb/pilotsyn.ps,<br />

2003.<br />

[5] w3.org. Well-formed xml documents. http://www.w3.org/TR/2000/REC-xml-<br />

20001006#sec-well-formed.<br />

[6] Perdita Stevens with Rob Pooley. Using UML: software engineering with objects and<br />

components. Object Technology Series. Addison-Wesley Longman, 1999. Updated edition<br />

for UML1.3: first published 1998 (as Pooley and Stevens).<br />

116

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!