Datalogi 0GB K-opgaven: DIKU Flight Simulator 2004
Datalogi 0GB K-opgaven: DIKU Flight Simulator 2004
Datalogi 0GB K-opgaven: DIKU Flight Simulator 2004
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