Datalogi 0 GB 2003 DIKU Flight Simulator. Espen Højsgaard Rune Højsgaard Sune J. Jensen

Størrelse: px
Starte visningen fra side:

Download "Datalogi 0 GB 2003 DIKU Flight Simulator. Espen Højsgaard Rune Højsgaard Sune J. Jensen"

Transkript

1 Datalogi 0 GB 2003 DIKU Flight Simulator Espen Højsgaard Rune Højsgaard Sune J. Jensen 1

2 Indhold 1 Sammenfatning Vores løsning Resultat Forløb Problemorienteret analyse Modelbeskrivelse Notationsmuligheder / -begrænsninger Strålesporing Kameramodel Lys Effektivitet Brugergrænseflade Fejlmeddelelser Løbende respons Objekt orienteret design Designovervejelser Vigtige designbeslutninger Diagrammer Programmeringsovervejelser Strålesporing Før sporingen Selve sporingen Tidskompleksitet Beregning af skæring med objekter Kompleksitet for en enkelt stråle Antal sporede stråler Programbeskrivelse Læsevejledning Kommentarer i koden Sceneopstiller Afprøvning Strategi Krævede attributter <scene> <pilotsyn> <sol> <kugle>

3 6.1.6 <plan> <mesh> <punkt> <farve> <trekanter> <trekant> <punkter> Opstilling og udførsel Konklusion Brugervejledning Det kan Fotograf Systemkrav Installation Afvikling af programmet Meddelelser Fejlmeddelelser Litteratur 31 A Klasser og arv 32 B Associationsdiagram 33 C CRC-kort 33 C.1 Element C.2 Fotograf C.3 Kamera C.4 Kugle C.5 Mesh C.6 Plan C.7 Punkt3D C.8 Scene C.9 Sceneopstiller C.10 Sol C.11 Stråle C.12 Trekant C.13 XMLParseError D Grænseflader 47 D.1 Klassen Element D.2 Klassen Fotograf D.3 Klassen Kamera D.4 Klassen KameraI

4 D.5 Klassen Kugle D.6 Klassen Mesh D.7 Klassen Plan D.8 Klassen Punkt3D D.9 Klassen Scene D.10 Klassen SceneI D.11 Klassen Sceneopstiller D.12 Klassen Sol D.13 Klassen Stråle D.14 Klassen Trekant D.15 Klassen XMLParseError E Kildekode 54 E.1 Element.java E.2 Fotograf.java E.3 Kamera.java E.4 KameraI.java E.5 Kugle.java E.6 Mesh.java E.7 Plan.java E.8 Punkt3D.java E.9 Scene.java E.10 SceneI.java E.11 Sceneopstiller.java E.12 Sol.java E.13 Stråle.java E.14 Trekant.java E.15 XMLParseError.java F Afprøvningsdata 84 F.1 Afprøvning F.2 Afprøvning F.3 Afprøvning F.4 Afprøvning F.5 Afprøvning F.6 Afprøvning F.7 Afprøvning F.8 Afprøvning F.9 Afprøvning F.10 Afprøvning F.11 Afprøvning F.12 Afprøvning F.13 Afprøvning

5 F.14 Afprøvning F.15 Afprøvning F.16 Afprøvning F.17 Afprøvning F.18 Afprøvning F.19 Afprøvning F.20 Afprøvning F.21 Afprøvning F.22 Afprøvning F.23 Afprøvning F.24 Afprøvning F.25 Afprøvning F.26 Afprøvning F.27 Afprøvning F.28 Afprøvning F.29 Afprøvning F.30 Afprøvning F.31 Afprøvning F.32 Afprøvning F.33 Afprøvning F.34 Afprøvning F.35 Afprøvning F.36 Afprøvning F.37 Afprøvning F.38 Afprøvning F.39 Afprøvning F.40 Afprøvning F.41 Afprøvning F.42 Afprøvning F.43 Afprøvning F.44 Afprøvning F.45 Afprøvning F.46 Afprøvning F.47 Afprøvning

6 1 Sammenfatning Dette er en besvarelse af den karaktergivende opgave på kurset Datalogi 0 GB 2003, Københavns Universitet [1]. Læseren forventes at have læst opgaveformuleringen samt - som minimum - at have samme forudsætninger som en elev, der har fulgt kurset. Formålet med opgaven var at udvikle et program, der implementerer en simpel flysimulator ved brug af strålesporing. 1.1 Vores løsning Vores ambition var at lave et godt objektorienteret design af den minimumsløsning, som opgaveteksten beskriver. Dette design skulle muliggøre nem tilføjelse af nye former og samtidig gøre det muligt senere at implementere mere avancerede lys- og kameramodeller. Det var vores mål, at det resulterende program korrekt skulle implementere de principper, der er beskrevet i opgaven, således at den udleverede scenebeskrivelse kunne omsættes fejlfrit til billeder Resultat Resultatet er blevet et design, der til fulde lever op til førnævnte ambitioner og som i sin struktur og navngivning bruger logiske analogier til den virkelige verden. Programmet lever ligeledes op til vores og opgaveformuleringens krav, hvilket afprøvningen bekræfter Forløb Opgaveforløbet har været præget af, at dette er vores første objektorienterede design og vi har derfor brugt meget tid på designet i forhold til programmets størrelse. Processen har dog været lærerig og resultatet må have en vis kvalitet, da selve kodningen kun tog lidt mere end én dag. Alt i alt har det været en interessant opgave og vi er tilfredse med resultatet. 6

7 2 Problemorienteret analyse Formålet med denne opgave er - som beskrevet i opgaveformuleringen [1] - at fremstille et program, der kan kan generere farvebilleder ud fra en modelbeskrivelse. Teknikken, der skal bruges, er strålesporing og de grundlæggende principper for denne teknik er beskrevet i opgaveformuleringen. Vi vil i dette afsnit diskutere såvel modelbeskrivelsen som strålesporingen, da ingen af dem er fuldstændigt afklaret i opgaveteksten. Endvidere vil vi diksutere hvilken brugergrænseflade programmet have. 2.1 Modelbeskrivelse Der er i opgaveteksten fastlagt en notation, der er baseret på XML. Denne notation inkluderer tags til beskrivelse af de elementer, som der skal laves billeder af, samt tags til lyskilder og til billedspecifik information. Da opgaveteksten ikke stiller krav til, hvordan programmet håndterer syntaktisk forkert XML, vil vi blot vedtage, at hvis det er tilfældet, så skal programmet skal meddele det til brugeren og så afslutte. Vi vil i det følgende undersøge om notationen er tilstrækkelig samt afdække det semantiske grundlag for notationen Notationsmuligheder / -begrænsninger Den givne notation indeholder følgende grundelementer: scene, pilotsyn, sol, kugle, plan og mesh. De sidste tre beskriver ting, der kan ses på de genererede billeder, mens de første tre er lidt mere uhåndgribelige. Vi vil starte med at diskutere de tags de har til fælles. Derefter vil vi diskutere de seks grundelementer hver for sig. Fælles tags De forskellige grundelementer deler to tags: punkt og farve. Disse skal leve op til nogle regler, som vi vil gennemgå her. punkt punkt-tagget lader brugeren specificere et sæt koordinater i tilknytning til et id. Et sådant koordinatsæt bruges til at beskrive to ting i notationen: punkter og vektorer. For begge gælder, at brugeren skal angive alle tre koordinater, da vi mener det vil gøre modelbeskrivelserne uoverskuelige, hvis man kan udelade et koordinat og i stedet lade det få en standard-værdi. For vektorer vil vi pålægge endnu et krav: mindst én af koordinaterne skal være forskellig fra nul. Dette skyldes at vektorer i notationen bruges til at angive retninger og nulvektoren har ikke én, men alle retninger. farve farve-tagget bruges til at angive en farve i RGB-systemet. I den model vi bruger, er der 8 bit til hver af værdierne, hvilket medfører at værdieren skal være heltal i intervallet [0;255]. Som for punkt-tagget vil vi kræve at alle tre værdier skal angives. 7

8 scene Scene-tagget pålægger notationen en enkelt begrænsning, da det er dokumentets rod. Begrænsningen er, at der kun kan være et scenetag - i hvert fald på yderste niveau - hvormed det er udelukket at der kan være flere scener i samme fil. Vi vil ikke gøre noget for at undgå den begrænsning, da vi mener at det er mest hensigtsmæssigt, kun at have en model i hver fil. pilotsyn Pilotsyn-tagget er vigtigt, da det fastlægger hvilke billeder, der skal laves af modellen. De pilotsyn, der kan laves med den givne notation, tager udgangspunkt i den model, der beskrives i opgaveformuleringen: et øjepunkt, et stedpunkt, to vektorer - der fastlægger vandret og lodret - samt en billedopløsning. Den model udelukker andet end plane synsflader, men da vores teori kun beskriver denne type, er det fuldt tilstrækkeligt. Tolkning af pilotsyn Det er i opgaveformuleringen ikke fastlagt, hvordan stedpunktet og vektorerne skal fortolkes, men der er på kursets hjemmeside blevet publiceret et dokument [3], der klarlægger dette. Stedpunktet er det nederste venstre hjørne af filmen og vektorerne fastlægger herudfra, hvilken retning der er op og hvilken der er til højre. Der er i notationen ikke noget, der forhindrer brugeren i at definere disse vektorer på en måde, så de ikke opfylder denne model. Desværre har vi ikke det fornødne matematiske kendskab til at kontrollere, at vektorerne lever op til modellens krav og vi kan derfor ikke implementere et fejltjek på dette - bortset fra tjek for at ingen af dem er nulvektoren, hvilket ikke har nogen mening. Et andet aspekt i modellen, der er interessant, er hvis brugeren placerer øjepunktet i det rektangel, som udgør filmen. Hvis øjepunktet kommer til at falde sammen med et punkt, hvorigennem der skal spores en stråle, vil strålen ikke have nogen retning og altså ikke være en stråle men et punkt. Der er ikke noget i vejen for at spore et punkt i modellen, og vi vil derfor ikke forsøge at begrænse brugerens placering af øjepunktet. Som det sidste vil vi slå fast, at opløsningen - bredde og højde - skal være heltal større end nul, da de angiver et antal felter. sol Sol-tagget angiver placering og farve af lyskilderne i scenen. Da vores teori kun beskriver strålesporing med en lyskilde, så vil vi kun tillade et sol-tag i en scene. Solens farve skal følge de generelle regler for farver, men derudover er der ikke nogen begrænsninger, da den givne lysmodel tillader alle farver. Former De sidste tre tags - især mesh - gør det muligt at beskrive særdeles komplicerede objekter og vi mener derfor at notationen med hensyn til modellering af fysiske former er fuldt tilstrækkelig. Det vil godt nok være en ganske omstændig proces at skulle beskrive selv de mest trivielle hverdagsting, hvis brugeren ikke har mulighed for at bruge et designværktøj, men det er muligt. Endvidere kan selv en simpel model illustrere et koncept, der kan være svært at visualisere for sit indre øje, hvorfor den simple notation også er brugbar uden et designværktøj. 8

9 Fælles for det tre former - som de tre tags kan beskrive - er, at vi ikke vil udvide notationen med mulighed for f.eks. refleksion og gennemsigtighed. Selvom sådanne egenskaber formentlig ville gøre billederne mere interessante, så ligger det udover vores teoretiske grundlag at indføre den slags effekter. Herunder vil vi kort gennemgå hver af de tre former og de begrænsninger, vi mener det er nødvndigt at pålægge dem. kugle En kugle defineres ved sit centrum, sin radius og sin farve. Centrum og farve skal leve op til de ting vi nåede frem til i starten af afsnittet. Radius skal være større end nul, da negativ radius ikke har nogen mening og da vi ikke mener at brugeren skulle have grund til at definere et enkelt punkt. mesh Et mesh er en samling af trekanter. Vi mener ikke at det har nogen mening at en trekant definerer et linjestykke eller et punkt og for at undgå det, vil vi kræve at alle punkterne i et mesh er forskellige og at en trekant bliver defineret ved tre forskellige punkter, der alle skal angives. plan En plan defineres ved et stedpunkt, to vektorer og en farve. Udover at skulle leve op til de fælles krav, så vil vi også kræve at de to vektorer ikke er parallelle, da der i så fald ikke udspændes en plan, men en linje, hvilket vi ikke mener har nogen mening. Dette kan undersøges, da to parallelle vektorer, a og b, vil opfylde følgende a = t b a 2 = t 2 b 2 a 2 = t 2 b 2 t = ± a Så hvis de to vektorer opfylder a = a b b eller a = a b b, så er de parallelle. 2.2 Strålesporing Vi skal som sagt bruge strålesporing til at lave billederne med. Teknikken går ud på at følge lysets vej fra solen til øjet - bare den modsatte vej. I dette afsnit vil vi afklare de uklarheder, som vi mener der er i opgaveteksten Kameramodel Som beskrevet i opgaveformuleringen [1, afs. 3], defineres der i modelbeskrivelsen en synsflade (eller flere) med et tilhørende øjepunkt og der knyttes endvidere en opløsning til hver synsflade. Opløsningen definerer hvor mange referencefelter synsfladen skal deles op i. Processen med at generere et billede, består i at bestemme hvilken farve hvert referencefelt skal have. Der er flere måder hvorpå farven i referencefelt kan bestemmes. Man kan f.eks. spore en stråle der går fra øjepunktet og igennem midten af referencefeltet, eller man kan spore en række stråler gennem refenrencefeltet og så bestemme farven som et vægtet gennemsnit af de fundne farve. 9 b

10 Hvis man kun sporer en enkelt stråle igennem et referencefelt, er det sandsynligt at man vil opleve en del alialisering, dvs. hakkede kanter o.l. Denne effekt skyldes at et referencefelt har en hvis fysisk udstrækning og det er ikke så sandsynligt at alle punkter i feltet vil have samme farve. Farven i enkelt punkt kan derfor ikke forventes at være repræsentativ for hele feltet. Alialisering vil formentlig kunne mindskes ved at spore flere stråler igennem et referencefelt, da det så er mere sandsynligt at den fundne farve er repræsentativ for feltet. Desværre har vi ikke noget grundlag for at vide hvor og hvor mange stråler, der skal spores for at opnå mindre alialisering og vi vil derfor nøjes med at spore en enkelt stråle igennem midten af hvert referencefelt Lys Lysmodellen - der beskrives i opgaven - tager én lyskilde i betragtning og tager ikke højde for refleksion eller andre fænomener, der - udover en solens direkte lys - kunne belyse et punkt. På trods af denne simple model, så er der alligevel nogle apekter, som ikke dækkes fuldt i opgaveformuleringen. Skygge Opgaveteksten beskriver hvordan man beregner farven i et punkt - hvis lyset altså rammer punktet. For det tilfælde at lyset fra lyskilden aldrig når til punktet, så ligger punktet i skygge, og skal derfor være sort. I den virkelige verden er der som bekendt ikke sort i skyggen, men i vores lysmodel er det det eneste naturlige valg, da der ikke kan komme lys fra andre retninger end solen. Intet ramt Et andet spørgsmål der skal afklares er, hvilken farve der skal være, hvis vi sporer en stråle der ikke rammer noget i modellen. Man kunne lade brugeren vælge en baggrundsfarve, hvilket f.eks. kunne bruges til at lave en blå himmel uden at skulle beskrive den. Denne mulighed er ikke understøttet i den givne notation, så vi vælger i stedet at lade farven i sådanne tilfælde være sort, da der aldrig vil komme lys fra den retning. Solen bag flader Opgaveteksten forholder sig ikke til det tilfælde, hvor en flade befinder sig mellem øjepunktet og solen. Det kunne f.eks. være at solen var placeret i en kugle eller at der var en plan imellem. I det tilfælde bør fladen - efter vores opfattelse - ikke få en farve, da vi ikke bruger gennemsigtige flader. Desværre har vi ikke fået matematiske værktøjer - og er ikke selv i stand til lave dem - til at bestemme om øjepunkt og sol befinder sig på hver sin side af fladen og vi er derfor ikke i stand til at implementere det aspekt. Det har den uhensigtsmæssige konsekvens, at en flade er synlig, selvom øjepunktet og synsfladen ligger i samme flades skygge Effektivitet Vi forventer at strålesporing er en tidskrævende proces og det er derfor vigtigt at overveje, om der er måder at effektivisere processen på. Opgaveteksten fremhæver f.eks. udregningen 10

11 af cosinus til vinklen mellem en flades normalvektor og en stråle, som et sted hvor der kan spares beregninger 1 [1, s. 8]. Simpel omsluttende form En metode vi forestiller os kan gøre strålesporingen hurtigere, er at beregne en simpel omsluttende form for hver af de mere komplekse former. Man kunne f.eks. ved et mesh, som består af en række trekanter, beregne en kugle ved indlæsningen af modellen, der lige præcis indeholdt alle trekanterne. Ved strålesporingen kunne man så bruge kuglen til at teste om meshet blev ramt, hvilket ville være nemmere end at skulle undersøge alle trekanterne for sig. Det ville man selvfølgelig skulle gøre i de tilfælfe, hvor strålen ramte kuglen, men i de fleste tilfælde tror vi at det ville være en fordel. Desværre kender vi ikke algoritmer til at beregne en sådan omsluttende form, og må derfor se bort fra idéen, men i en videreudvikling af programmet, ville det nok være værd at undersøge. Frasortering af dele En anden metode, som vi mener ville gøre processen hurtigere, er fjerne de dele af scenen, som er helt uden for synsfeltet. Dette ville kunne gøres før generereringen af et billede og ville mindske det antal former, som skulle testes for skæring med hver stråle. En måde at gøre det på, kunne være at definere en (uendelig) pyramide ud fra ø- jepunktet og fire stråler; en gennem hvert hjørne af synsfladen. Herefter kunne man under genereringen af billedet, se bort fra alle objekter, der lå uden for pyramiden. Igen er vi desværre begrænset af vores kendskab til rumgeometrien, men ligesom med de omsluttende former, ville det være en oplagt tilføjelse til en senere udgave. 2.3 Brugergrænseflade I dette afsnit vil vi undersøge, hvordan programmets grænseflade til brugeren skal være. Programmet behøver ikke en interaktiv grænseflade, da brugeren kan specificere alt programmet skal/kan bruge i en XML-fil. Men der er flere sammenhænge, hvor det vigtigt at programmet melder tilbage til brugeren. F.eks. hvis brugeren har lavet en fejl i XMLfilen Fejlmeddelelser Da vi ikke stiller et designværktøj til rådighed for brugeren, så er der rigelig mulighed for at brugeren kan lave fejl. Det er derfor vigtigt, at der kommer fejlmeldinger til brugeren, som kan hjælpe hende med lokalisere fejlen. Da den givne notation inkluderer en id-attribut til de fleste tags, vil det være oplagt at bruge id et til at fortælle brugeren, hvor der er fejl. Hvis der f.eks. ikke er angivet en farve til en plan kaldet jord, så vælger vi at give brugeren meddelelsen 1 ved at udnytte sammenhængen a ( b = cos ( a, ) b) a b 11

12 jord (plan)->farve Farve skal angives På den måde kan brugeren se id et og typen på det tag hun skal kigge efter Løbende respons For at undgå at brugeren tror at programmet er gået i stå, vil vi give brugeren besked, hver gang en ny del-proces sættes igang og når de afsluttes igen. Da vi som sagt forventer, at strålesporing er en tidskrævende proces, mener vi at det især er vigtigt, at brugeren løbene får respons fra programmet, når et billede bliver lavet. Vi vælger derfor at vise brugeren hvor langt genereringen af et givet billede er, ved at skrive et stjerne for hver 10%. Givet et pilotsyn syn1 skal beskeden - når et sted mellem 70% og 80% er færdig - se ud som følger: Laver billede "syn1": ******* 12

13 3 Objekt orienteret design Ud fra opgaveteksten og ovenstående overvejelser, har vi lavet et objektorienteret design. Dette er sket med udgangspunkt i Erics OOD kogebog [2] samt Perdita [4]. I det følgende afsnit vil vi diskutere designet. I tilæg til teksten har vi i appendiks B placeret et associationsdiagram, i app. A et diagram med klasserne og deres grænseflader og i app. C har vi placeret de CRC-kort vi er nået frem til. Især de to første giver et godt overblik over designet og bør derfor studeres sammen med teksten. 3.1 Designovervejelser Vi har valgt en overordnet struktur som går ud på at der er en Fotograf som sætter en Sceneopstiller til at indlæse scenespecifikationerne fra en XML-fil, og opbygge en Scene (ved at fylde den med en Sol, og en mængde Elementer og Kameraer). Når en Scene er opbygget aktiverer Fotografen Kameraerne ét ad gangen. Når et Kamera bliver aktiveret skyder det Stråler gennem et antal reference-punkter, ind i Scenen. Scenen indeholder en liste over hvilke Elementer (inkluderer de forskellige figur klasser, som pt. er Kugle, Trekant, Mesh og Plan), som findes i Scenen, og gennemgår dem alle, for at finde ud af hvilket af Elementerne som er det første en given Stråle skærer. Når en Stråles første skærings3dpunkt er defineret, skydes der endnu en stråle, denne gang fra den Sol som findes i Scenen, til skærings3dpunktet mellem den første Stråle og Elementet. Alt afhængig af vinklen mellem Strålen fra Solen og skærings3dpunktet, og farven af Elementet, findes en farve som den første Stråle antager, og vender tilbage til Kameraet med. Kameraet tildeler så det referendepunkt som Strålen blev skudt ud igennem, den farve som Strålen kom tilbage med. Når alle referencepunkterne er bearbejdede, gemmer kameraet resultatet i en fil Vigtige designbeslutninger I løbet af anden iteration i henhold til [2], foretog vi nogle af de vigtigste designmæssige beslutninger. I første iteration var klassen Scene, i tilgift til til de ansvar klassen stadig har, blevet gjort ansvarlig for både at indlæse XML, opbygge scenen og gemme billedet i en fil. fordelen ved en sådan monolith er at der skal flyttes meget lidt data: En central klasse tager sig af hovedparten af beregninger og databearbejdning, resten af klasserne indeholder mere eller mindre statisk data, og nogle få funktioner. Nogle af Problemerne med den løsning er bl.a. at man får et program med meget høj kobling, og derfor kan selv små ændringer i dele af programmet, få uoverskuelige konsekvenser. Det betyder også at en høj modularitet er stort set uopnåelig. Vi valgte at løse problemet ved hjælp af to tiltag: for det første valgte vi at overlade ansvaret for at gemme billedet, til klassen Kamera. Et logisk tiltag, da det er denne k- lasse som genererer billedet. For det andet besluttede vi at oprette en ny klasse ved navn Sceneopstiller, som fik ansvaret for at læse XML-filen, oprette scenen og tilføje figurer til Scenen. 13

14 XML til intern kobling Efter anden Iteration blev vi opmærksomme på at vi blot havde flyttet en del af problemet: klassen Sceneopstiller havde stadig en meget høj kobling. Efter at have analyseret problemet besluttede vi os dog for at beholde Sceneopstiller uforandret. Det beror på at vi kom frem til at de fleste koblinger mellem Sceneopstiller og andre klasser, går ud på at Sceneopstiller instansierer klasserne med data fra XML-filen som argumenter, og derefter ophører al kontakt. Problemet er naturligvis at man er nødt til at ændre i Sceneopstiller, hvis man ændrer på en af figurerne eller tilføjer en ny figur. Vi erkendte at figurerne alle er så forskellige, at det ville være meget omstændigt at prøve at definere en eller anden fælles skabelon som de alle skulle overholde. Samtidig mener vi at det er hensigtsmæssigt at holde XML-indlæsningen og sceneopbygningen samlet i én klasse, for at holde koblingen mellem intern og ekstern representation af figurer samlet, så vi kun behøver at rette ét sted, hvis en figur ændres eller tilføjes. Et kompromis hvor hensigten har været at fremme enkelthed og modularitet. Grænseflader og generalisering Efter 2. iteration havde vi 3 grænseflader (SceneI, SceneopstillerI, KameraI) og 1 abstrakt klasse (Element). I løbet af 3. iteration gennemgik vi hver af dem, og overvejede deres berettigelse. SceneI giver god mening at have som grænseflade, man kunne nemt forestille sig tilfælde, hvor det ville være hensigtsmæssigt at implementere en ny Scene klasse. Det kunne f.eks være hvis man ønskede en model som understøttede flere lyskilder eller implementerede en smartere metode til at finde en Stråles første skærings3dpunkt. Samtidig gør både Sceneopstiller og Kamera klasserne brug af grænsefladen. Alt i alt besluttede vi at beholde SceneI. SceneopstillerI har bestemt også merit. En af årsagerne til at vi valgte at holde XMLindlæsningen og sceneopbygningen samlet i én klasse, var jo netop at det gav absolut mest mening at udskifte det hele på én gang. Efter nogen granskning kom vi dog frem til at der simpelthen ikke var tilstrækkeligt med efterspørgsel, til at det kunne berettige en grænseflade: den eneste klasse som ville gøre brug af grænsefladen var Fotograf, og Fotograf ville næppe nogensinde komme til at sende (og modtage) mere end én besked (muligvis i en senere udgave, samme type besked flere gange), til Sceneopstiller, under en kørsel. Meget væsentligt i vore overvejelser var også det faktum at der under kørsel aldrig ville blive instansieret mere en én Sceneopstiller. SceneopstillerI blev altså strøget. KameraI er et grænsetilfælde, fordi den har merit men ikke er videre efterspurgt (ligesom SceneopstillerI), og fordi vi alligevel har besluttet os for at beholde den. Der kunne være mange grunde til at lave kameraer med udvidet funktionalitet, f.eks et kamera som efter at have genereret et billede, skiftede position og gentog processen. Kamera bliver instansieret af Sceneopstiller (bag om grænsefladen), og derefter er det kun Fotograf som benytter sig af grænsefladen (og kun én gang pr. Kamera). Det der gjorde at vi alligevel besluttede os for at grænsefladen er berettiget, er at den i høj grad kunne blive relevant i en situation hvor der findes en række forskellige kameraer, som har forskellige egenskaber. I et sådant tilfælde ville enkapsuleringen Kamera, gøre programmet langt mere overskueligt og funktionelt ([4] opfordrer i høj grad til brug af enkapsulation). 14

15 Element ville være meget velegnet som grænseflade. Uanset deres geometriske egenskaber, er det de samme data vi ønsker fra alle de forskellige figurer: skæringspunkt og farve. Netop med figurene er der dog endu en faktor at tage med i overvejelserne: der er nogle mekaniske beregninger som skal udføres for alle figurer uden undtagelse, mht. skæring med strålen fra solen, og den resulterende farve. De beregninger gør at det er attraktivt at gøre Element til en abstrakt klasse i stedet for en grænseflade. Det er fordi vi så har mulighed for at genbruge kode som står i Element, i stedet for at skrive koden i hver enkelt af figur-klasserne (kode genbrug anbefales også på det kraftigste i [4]), og giver yderligere den fordel at man kun behøver at rette èt sted, hvis der senere skal ændres i koden. Desuden fremmes det mål, som opgaveteksten lægger vægt på, om at nye former nemt skal kunne tilføjes til designet. For at tilføje en ny form til designet, skal den blot nedarve fra Element - og opfylde dennes kontrakt - og en XML-til-intern kobling skal tilføjes til Sceneopstiller. Bekvemmelsesklasser Efter at designfasen var overstået, og vi var begyndt at kode, måtte vi erkende at det ville være hensigtsmæssigt med nogle simple datastrukturer, som skulle bruges som argumenter, af de forskellige klasser. Vi oprettede to forskellige klasser: 3DPunkt og Stråle. Begge indeholder data som kan inspiceres og evt. ændres, men ingen af dem sender selv meddelelser til andre objekter, og de har som sådan ingen faste associationer med nogle bestemte klasser, ud over at klasserne bruger dem som datastrukturer og argumenter. Det afspejler vi i diagrammerne ved ikke tegne nogle associationer mellem disse to klasser og resten af klasserne, på associationsdiagrammet, og ved at udelade disse to i sekvensdiagrammet, alt sammen for overskuelighedens skyld. Mens vi kodede valgte vi også at introducere en klasse XMLParseError, som kastes ved fejl i indlæsningen af XML-filen. Denne stammer fra den udleverede XML-indlæser. 3.2 Diagrammer Her følger en kort beskrivelse af hvert diagram, og begrundelsen for at tage dem med. associationsdiagrammet er resultatet af vores arbejde med [2]. Det viser alle programmets klasser, og deres indbyrdes forhold. Associationerne er holdt på et generelt niveau, for at gøre det nemt at overskue diagrammet, men vi har dog inkluderet metoderne for hver klasse, så man nemt og hurtigt kan referere til dem. Dette diagram er tegnet før programmet er kodet/da vi begyndte at kode programmet, og vi har hovedsaligt kodet ud fra dette diagram. nedarvningsdiagrammet er genereret efter at programmet er kodet, og er med for at give et overblik over hvilke klasser som nedarver fra hvilke. Desuden viser vi klassernes grænseflader på dette diagram, da det formentlig er rart at have et overblik over disse når man skal arbejde med programmet. Vi har særligt tænkt på folk som evt. skulle vedligeholde eller udvide programmet. CRC-kortene stammer fra vores designfase og viser ansvarsfordelingen og de tilhørende kollaboratører. Det er værd at bemærke at vi ikke har flyttet ansvaret beregn skæring 15

16 med stråle op i den generelle klasse Element, da denne er abstrakt. I stedet står ansvaret på hver af dens underklasser. Dette skyldes at implementationen af dette ansvar ikke kan generaliseres. 16

17 4 Programmeringsovervejelser Det er vores opfattelse, at ovenfor gennemgåede design kan implementeres som det er. Vi vil derfor ikke beskæftige os yderligere med programmets overordnede struktur i dette afsnit. I stedet vil vi diskutere strålesporingsalgoritmen og dennes tidskompleksitet. 4.1 Strålesporing Der er i opgaveteksten [1, s.7] skitseret en algoritme til strålesporing. Vi vil følge denne algoritme og i det følgende vil vi gennemgå de enkelte trin og løse evt. problemer Før sporingen I vores design er det et Kamera-objekt, der skal stå for opdelingen af filmen i referencefelter og for at skabe de Stråle-objekter, der skal spores. Da vi skal bruge den udleverede klasse Kanvas til at skabe billedet, vil det være hensigtsmæssigt, hvis vores kamera opererer med et koordinatsytem, der direkte svarer til det Kanvas bruger. Dette (todimensionale) koordinatsystem har omdrejningsretning med uret og svarer derfor ikke til det koordinatsystem, som fastlægges af filmens stedpunkt og dens to vektorer. For at opnå korrespondance mellem de to koordinatsystemer beregner vi koordinatsættet til filmens øverste venstre hjørne ved at lægge lodret-vektoren til stedpunktet. Derefter vender vi lodret-vektoren om. Som det sidste skalerer vi lodret-vektoren og vandret-vektoren, så de henholdsvis får samme længde som højden og bredden af et referencefelt. Hvis vi kalder det nye stedpunkt for s, den nye lodret-vektor for l og den nye vandret-vektor for v, så har vi nu følgende korrespondance mellem et koordinatsæt (i, j) i Kanvas, til et koordinatsæt i scenen: (x, y, z) = s + (i + 0, 5) v + (j + 0, 5) l i, j N At der skal lægges 0,5 til kanvas-koordinaterne skyldes, at vi i de problemorienterede analyse besluttede at strålerne skulle gå midt igennem referencefelterne. Når vi har oprettet et Kanvas-objekt, er vi klar til at begynde strålesporingen Selve sporingen For hvert referencefelt skal vi nu gennemgå følgende trin: 1. Vi skal oprette en Stråle med udgangspunkt i øjepunktet og med retning mod midten af referencefeltet. 2. Scene-objektet skal finde ud af hvilke Element-objekter, strålen skærer og hvilket den skærer nærmest. Hvis Strålen ikke skærer nogen Elementer, så skal referencefeltet være sort. 3. Dernæst skal Sol-objektet lave en Stråle, der starter i solen og har retning mod det fundne skæringspunkt. 17

18 4. Scene-objektet skal finde det nærmeste skæringspunkt til solstrålen. 5. Det sidst fundne skæringspunkt skal sammenlignes med det første. Hvis de ikke er ens, så skal referencefeltet være sort. 6. Det ramte Element skal ud fra solstrålen bestemme sin farve i det ramte punkt. 7. Den fundne farve skal tildeles referencefeltet. Disse trin er trivielle at implementere, men punkt 5 kræver noget omtanke. Da vi arbejder med brudne tal kan der være visse præcisionproblemer. Det kan tænkes at selvom det med uendelig præcision ville være det samme punkt, der blev fundet ved udregning af skæring med både kamera- og solstråle, så kan præcisionsproblemerne betyde at det ikke er tilfældet i computerens repræsentation af de to skæringspunkter. Sammenligningen af de to punkter må derfor være tolerant overfor mindre unøjagtigheder. Vi har ikke noget grundlag for at vælge, hvor stor en differens der er acceptabel, og det må derfor bero på eksperimenter under konstruktionen af programmet. 4.2 Tidskompleksitet Der er to parametre det er interessant at undersøge tidskompleksiteten for strålesporingen i forhold til. Den første er antallet af objekter i scenen, den anden er det ønskede billedes opløsning. Da der i vores algoritme er en én til én korrespondance mellem antallet af pixels og antallet af sporede stråler fra kameraet, så er det i realiteten kun betydningen af antallet af objekter, der skal undersøges. Vi vil i den sammenhæng ikke betragte et mesh som et objekt. I stedet vil vi tælle de trekanter, der indgår i meshet, som objekter Beregning af skæring med objekter For både trekant, kugle og plan gælder, at udregningen af skæringspunkt(er) med en stråle er uafhængig af antallet af objekter i scenen. Disse udregninger bidrager derfor kun med konstanter til tidskompleksiteten i forhold til antallet af objekter Kompleksitet for en enkelt stråle Den variable størrelse for sporingen af en stråle i en scene er hvor mange objekter, der skal testes for skæring. Da disse skæringsudregninger er konstante i forhold til antallet af objekter, så er tidskompleksiteten for sporingen af en enkelt stråle lineært afhængig af antallet af objekter, n, dvs. O(n) Antal sporede stråler For hver stråle fra kameraet er der to muligheder: strålen rammer noget eller den rammer ikke noget. Hvis strålen rammer noget skal der spores endnu en stråle, ellers er vi 18

19 færdige. Dvs. at tidskompleksiteten i begge tilfælde - henholdsvis værste- og bedstetidskompleksiteten - afhænger lineært af tidskompleksiteten for sporing af to stråler. Derfor er afviklingstiden i forhold til antallet af objekter, n, i scenen asymptotisk tæt begrænset af funktionen f(n) = n, hvorfor vi har Θ(n). 19

20 5 Programbeskrivelse Dette er beskrivelsen af det færdige program. Læseren forventes at være på samme niveau, som en studerende på DIKU, der har fulgt Dat0GB-kurset til ende. Programmet følger det design, vi har beskrevet i afsnit 3 og de overvejelser vi har gjort i forrige afsnit. Kildekoden kan ses i appendiks E. Koden er velkommenteret og implementationsdetaljer må søges der. Alle klasserne og deres grænseflader er beskrevet i appendiks D. Følgende liste er forslag til relevante klasser i forbindelse med forskellige opgaver. I forbindelse med tilføjelse af en ny form, f.eks. en kasse, er det relevant at se på klasserne Element (app. D.1) og Sceneopstiller (app. D.11). Se desuden nedenstående afsnit om Sceneopstiller. Programmet kan bruges som modul i et andet program, se Fotograf afsnit D.2. I sin nuværende form forudsætter dette dog, at hovedprogrammet sikrer sig at XML-filen er gyldig, da vores program ellers kalder System.exit-metoden. Ved implementation af nye kameramodeller, der f.eks. implementerer anti-alialisering, er klasserne KameraI (app. D.4)og Sceneopstiller (app. D.11) gode steder at starte. 5.1 Læsevejledning Koden i hver klasse er delt op i følgende dele: 1. Evt. konstruktører er placeret først. 2. Dernæst kommer klassens metoder i alfabetisk rækkefølge (undtaget dem der falder under næste punkt). 3. Klassens accessors og mutators er samlet næstsidst. 4. Sidst kommer klassens attributter. Vi har tilstræbt at bruge danske navne på såvel variable som metoder, men har i få tilfælde - hvor vi skønnede det naturligt - brugt engelske navne. 5.2 Kommentarer i koden Hver metode er ledsaget af en forudgående beskrivelse af formålet. De løbende kommentarer i selve metoderne tilstræber at give en overordnet forklaring af fremgangsmåden. Klasserne indeholder en kort beskrivelse af deres formål, men en uddybning af denne information må søges i appendiks D. 20

21 5.3 Sceneopstiller Klassen Sceneopstiller er lavet med udgangspunkt i Søren Sjørups XMLReadWrite, der er stillet til rådighed i.f.m. opgaven. Denne kan hentes på kurset hjemmeside. Sceneopstiller er stærkt modificeret og kommenteringen lader en del tilbage at ønske, hvilket bunder i oplæggets sparsomme kommentering. Det er hver at bemærke, at Sceneopstiller bruger backtracking - ved hjælp af XML- ParseError - til at opbygge sine fejlmeddelelser. Ved brug af de generelle indlæsningsfunktioner er det derfor vigtigt at følge denne struktur, således at en konsistent fejlmelding kan gives til brugeren. 21

22 6 Afprøvning Da vi nu har implementeret programmet og ved at det syntaktisk er korrekt, vil vi afprøve om det semantisk lever op til opgaveformuleringens krav samt til vores egne krav fra den problemorienterede analyse. Det bliver i opgaven præciseret [1, afs. 5] at det er den eksterne afprøvning, der skal dokumenteres. Vi vil derfor ikke gå ind i den interne afprøvning, men blot konstatere, at vi under konstruktionen af programmet løbende har foretaget intern afprøvning. 6.1 Strategi Da det eneste input, som programmet får, er XML, så vil vi opdele kravene til programmet ud fra de tags, der er i den givne notation. For hvert tag vil vi undersøge, hvilke ækvivalensklasser man kan dele de mulige variationer op i og hvordan det kan kontrolleres at programmet lever op til kravet og herunder om det er muligt at vælge grænsetilfælde. For hver ækvivalensklasse vil vi skrive en parentes med nummeret på den relevante afprøvning. For de fleste tags vil der være to overordnede ækvivalensklasser: korrekt brug og forkert brug. Vi vil for disse tags behandle hver af disse ækvivalensklasser for sig. Generelt vil vi ikke beskæftige os med syntaktisk forkert XML, da kravet blot er at programmet skal kunne indlæse en scenespecifikation skrevet i XML. Som besluttet i den problemorienterede analyse, så skal en syntaktisk forkert scenebeskrivelse blot afvises af programmet. Vi vil starte med et generelt afsnit, der gælder for de tags, der har krævede attributter Krævede attributter For de tags, hvor der er et antal attributter der er krævede, er der to typer fejl: en eller flere manglende attributter eller fejl i en eller flere af disse. Hver af disse udgør en ækvivalensklasse for det relevante tag. Manglende attribut(ter) Test af programmets reaktion på manglende attributter er ens for de forskellige tags og vi diskuterer det derfor samlet her og vil ikke nævne det under de respektive tags (bortset fra en reference til den relevante afprøvning). Vi vil betragte de tilfælde, hvor en attribut er navngivet forkert, som om de ikke er angivet. Der er ikke noget oplagt grænsetilfælde for test af manglende attributter, da de alle er påkrævede uden nogen særlig vægtning e.l. Udeladelse af én enkelt af attributterne anser vi derfor for en repræsentativ test af denne ækvivalensklasse <scene> scene-tagget er rod-elementet i dokumentet og har ikke nogen krævede attributter. Der er derfor to ækvivalensklasser i forbindelse med scene-tagget: roden er scene (afpr. 1) eller 22

23 roden er noget andet (afpr. 2). Sidstnævnte mulighed skal resultere i en fejlmeddelelse. Det er ikke muligt at vælge grænsetilfælde, da det er enten eller <pilotsyn> For pilotsynet er det semantiske krav til beskrivelsen, at alle dets attributter skal være specificeret og det selvfølgelig korrekt. Korrekt pilotsyn Et korrekt angivet pilotsyn skal have den effekt, at der bliver lavet et tilsvarende billede, som efter kørslen ligger i en fil. Filen skal have det navn som er angivet i id-attributten og påhæftet endelsen.ppm. Endvidere skal programmet under kørslen give en løbende respons på processen. (afpr. 1) Kontrollen af at programmet lever op til dette krav beror på et visuelt skøn af det producerede billede samt at outputtet er som beskrevet. Forkert pilotsyn Et forkert angivet pilotsyn skal resultere i en fejlmeddelelse til brugeren, der angiver hvad fejlen er. Forkerte pilotsyn er dem, hvor der mangler en eller flere attributter (afpr. 3) eller hvor en eller flere af disse er angivet forkert. Forkert(e) attribut(ter) Fire af pilotsyn-taggets attributter består af punkt-tags og de vil blive diskuteret og afprøvet separat. Tilbage er id, hoejde og bredde. id kan ikke angives forkert 2. De to andre skal være heltal større end nul. Dette giver følgende ækvivalensklasser til test af forkert højde og bredde Værdien er ikke et tal. En test-værdi, der nærmest er en grænseværdi, vil være en blanding af tal og bogstaver. (hoejde: afpr. 4, bredde: afpr. 5) Værdien er et brudent tal. En grænseværdi kunne være et brudent tal, hvor decimaldelen var nul (f.eks. 0.0). (hoejde: afpr. 6, bredde: afpr. 7) Værdien er et heltal mindre end eller lig nul. Gænseværdien her er nul. (hoejde: afpr. 8, bredde: afpr. 9) <sol> Det overordnede krav for sol-tagget er, at der kun må være en sol i scenen. Som med pilotsyn, så skal alle sol-taggets attributter specificeres og det korrekt. Korrekt sol Da solen i sig selv ikke er synlig, kan en korrekt angivet sol kun kontrolleres, hvis der er objekter i synsfeltet og hvis solens farve er lys nok. Kontrollen beror på et visuelt skøn af det producerede billede. (afpr. 1) 2 id et kan indeholde tegn som det underliggende filsystem ikke kan håndtere. Dette har dog ikke noget med vores program at gøre 23

24 Forkert sol Manglende attributter er en fejl og dette testes som beskrevet i starten af afsnittet. (afpr. 10) sol-tagget har kun en attribut, der ikke testes for håndtering af forkert brug et andet sted, nemlig id og id kan ikke angives forkert <kugle> Kugle har fire attributter, hvoraf de to bliver beskrevet og testet i anden sammenhæng. Tilbage er test af id og radius. Id kan ikke angives forkert. Radius skal være et tal større end nul. Korrekt kugle En korrekt angivet kugle kan kun kontrolleres visuelt. (afpr. 1) Forkert kugle Alle kugle-taggets attributter er krævede, hvorfor de generelle betragtninger i starten af afnittet er relevante for kugle (afpr. 11). Specifikt for kugle er det kun radius, der skal testes. Vi mener der er følgende to ækvivalensklasser for forkert angivelse af kugle radius er ikke et tal. En form for grænsetilfælde vil være en blanding af tal og bogstaver. (afpr. 12) radius er nul eller derunder. Grænsetilfældet er nul. (afpr. 13) <plan> Plan har fem krævede attributter, hvoraf de fire bliver diskuteret og testet andetsteds. Den sidste er id og den kan ikke være forkert. De to af plans attributter afhænger af hinanden, nemlig de to retningsvektorer, der ikke må have samme retning. Korrekt plan En korrekt plan kan kun bekræftes visuelt. (afpr. 1) Forkert plan Hvis de to retningsvektorer er parallelle, så skal programmet komme med en fejl. Der er ikke noget grænsetilfælde, da det er et enten eller spørgsmål. (afpr. 14) (manglende attributter: afpr. 15) <mesh> Mesh har fire attibutter, hvoraf kun id - der ikke kan angives forkert - ikke testes i anden sammenhæng. Alle mesh s attributter er krævede. To af mesh s attributter er afhængige af hinanden, nemlig punkter og trekanter. Der må ikke være referencer i trekanter til punkt-tags, der ikke er defineret. Korrekt mesh Et korrekt mesh kan kun bekræftes visuelt. (afpr. 1) 24

25 Forkert mesh Ugyldige referencer i trekanter skal resultere i en fejlmeddelelse. Det er ikke muligt at vælge grænsetilfælde. (afpr. 16) (manglende attributter: afpr. 17) <punkt> Punkt har to betydninger i notationen: punkt og vektor. Kravende til de to er ens, bortset fra at vektorer ikke må være nulvektoren. Alle punkts attributter er krævede. Et punkts id kan kun være forkert i konteksten. Korrekt punkt/vektor Et korrekt punkt/vektor kan kun kontrolleres i forbindelse med de tags, der har en visuel effekt. Kontrollen består af et visuelt skøn. (afpr. 1) Forkert punkt/vektor Et forkert punkt eller vektor skal resultere i en fejlmeddelelse. De tre attributter x, y og z, har samme krav: de skal være tal. Dette giver kun en ækvivalensklasse med forkert data, nemlig de tilfælde hvor det ikke er tal (x: afpr. 18, y: afpr. 19, z: afpr. 20). En (form for) grænseværdi er en blanding af tal og bogstaver. For vektor er der desuden det tilfælde, hvor de fire attributter hver for sig er ok, men hvor x, y og z alle er nul. (afpr. 21) (manglende attributter: afpr. 22) <farve> Farve har tre attributter, der alle er påkrævede. De tre attributter skal være heltal i intervallet [0;255]. Korrekt farve En korrekt farve kan kun testes i forbindelse med de tags, der kan ses på det genererede billede. (afpr. 1) Forkert farve En forkert angivet farve skal resultere i en fejlmeddelelse. Der er fire ækvivalensklasser (for forkert data) for hver af de tre attributter: Værdien er ikke et tal. Grænseværdien er en blanding af tal og bogstaver. (r: afpr. 23, g: afpr. 24, b: afpr. 25) Værdien er et brudent tal. Grænseværdien er et brudent tal, hvor decimaldelen er nul. (r: afpr. 26, g: afpr. 27, b: afpr. 28) Værdien er et heltal, der er mindre end nul. Grænseværdien er -1. (r: afpr. 29, g: afpr. 30, b: afpr. 31) Værdien er et heltal, der er større end 255. Grænseværdien er 256. (r: afpr. 32, g: afpr. 33, b: afpr. 34) (manglende attributter: afpr. 35) 25

26 <trekanter> trekanter har en krævet tag: antal_trekanter. Dennes værdi skal svare til det antal trekantattributter, der er angivet. Korrekt trekanter Et korrekt angivet trekanter-tag kan kun testes i forbindelse med mesh-tagget. Kontrollen er visuel. (afpr. 1) Forkert trekanter Hvis antal_trekanter er angivet forkert, skal der komme en fejlmeddelelse. Der er fire ækvivalensklasser for forkerte værdier af antal_trekanter: Værdien er ikke et tal. Grænseværdien er en blanding af tal og bogstaver. (afpr. 36) Værdien er et brudent tal. Grænseværdien er et brudent tal, hvor decimaldelen er nul. (afpr. 37) Værdien er et heltal, der er mindre end nul. Grænseværdien er -1. (afpr. 38) Værdien er et heltal, der ikke svarer til antallet af trekant-attributter. (afpr. 39) (manglende attribut: afpr. 40) <trekant> trekant har tre krævede attributter. De må ikke være ens og skal være heltal større end eller lig nul. Korrekt trekant En korrekt trekant kan kun testes i forbindelse med et mesh-tag. Kontrollen er visuel. (afpr. 1) Forkert trekant En forkert trekant har to eller flere attributter med samme værdi. Grænseværdien er to ens attributter. (afpr. 41) (manglende attributter: afpr. 42) <punkter> punkter har en krævet tag: antal_punkter. Dennes værdi skal svare til det antal punktattributter, der er angivet. Korrekt punkter Et korrekt angivet punkter-tag kan kun testes i forbindelse med meshtagget. Kontrollen er visuel. (afpr. 1) 26

27 Forkert punkter Hvis antal_punkter er angivet forkert, skal der komme en fejlmeddelelse. Der er fire ækvivalensklasser for forkerte værdier af antal_punkter: Værdien er ikke et tal. Grænseværdien er en blanding af tal og bogstaver. (afpr. 43) Værdien er et brudent tal. Grænseværdien er et brudent tal, hvor decimaldelen er nul. (afpr. 44) Værdien er et heltal, der er mindre end nul. Grænseværdien er -1. (afpr. 45) Værdien er et heltal, der ikke svarer til antallet af trekant-attributter. (afpr. 46) (manglende attribut: afpr. 47) 6.2 Opstilling og udførsel Herunder følger de nævnte afprøvninger. Inddata samt forventet og faktisk uddata er placeret i appendiks F og de respektive kolonner i nedenstående tabel, refererer til afsnit i dette appendiks. Den sidste kolonne i tabellen angiver om afprøvningen forløb som forventet. Nr. Inddata Forventet uddata Faktisk uddata Kommentar 1 F.1 F.1 F.1 obligatorisk 2 F.2 F.2 F.2 3 F.3 F.3 F.3 4 F.4 F.4 F.4 5 F.5 F.5 F.5 6 F.6 F.6 F.6 7 F.7 F.7 F.7 8 F.8 F.8 F.8 9 F.9 F.9 F.9 10 F.10 F.10 F F.11 F.11 F F.12 F.12 F F.13 F.13 F F.14 F.14 F F.15 F.15 F F.16 F.16 F F.17 F.17 F F.18 F.18 F F.19 F.19 F F.20 F.20 F.20 / 27

28 Nr. Inddata Forventet uddata Faktisk uddata Kommentar 21 F.21 F.21 F F.22 F.22 F F.23 F.23 F F.24 F.24 F F.25 F.25 F F.26 F.26 F F.27 F.27 F F.28 F.28 F F.29 F.29 F F.30 F.30 F F.31 F.31 F F.32 F.32 F F.33 F.33 F F.34 F.34 F F.35 F.35 F F.36 F.36 F F.37 F.37 F F.38 F.38 F F.39 F.39 F F.40 F.40 F F.41 F.41 F F.42 F.42 F F.43 F.43 F F.44 F.44 F F.45 F.45 F F.46 F.46 F F.47 F.47 F.47 / 6.3 Konklusion Som det ses af ovenstående tabel, så klarer den endelige udgave af vores program sig igennem afprøvningen. Det er dog ikke resultatet af første afprøvning, der ses ovenfor. Især afprøvning 1 afslørede flere betydelige fejl. Heriblandt en fejl i Trekant klassen, der bevirkede at omkring halvdelen af billedet syn2.ppm blot var vandrette grå og sorte streger. Fejlen skyldtes at den implementerede algoritme til projicering på en plan ikke brugte den numeriske værdi af plankonstanterne, hvorfor trekanterne ikke nødvendigvis blev projiceret ind på den plan, hvor deres projektion havde størst areal. De resterende afprøvninger afslørede ikke vitale fejl i programmet, men var med til at trimme fejlmeldingen fra programmet, hvilket fra brugerens synspunkt må siges at være væsentligt. 28

29 7 Brugervejledning Dette er brugervejledningen til strålesporeren Fotograf. Det forudsættes at læseren kan lave scenebeskrivelser som beskrevet i [1]. Endvidere forudsættes kendskab til hvordan man bruger en kommandofortolker. 7.1 Det kan Fotograf Fotograf er et Java-program, der kan lave billeder af tredimensionale modeller og gemme dem i ppm-formatet. I sin nuværende form kan du bruge Fotograf til at lave billeder, hvor der indgår kugler, planer og trekanter. Selvom det ikke lyder af meget, så kan du faktisk lave ret flotte billeder med de tre former. Men før du kan lave dit første billede, skal du først have installeret Fotograf på dit system. 7.2 Systemkrav For at du kan køre Fotograf, skal en Java-fortolker være installeret på dit system. Javafortolkere til de fleste platforme kan hentes på internet-adressen og der kan du også finde information om hvordan de installeres og sættes op. 7.3 Installation Installation af Fotograf kræver lidt kendskab til, hvordan dit system fungerer. Du skal nemlig sørge for, at den såkaldte classpath indeholder stien til den mappe, hvor du har placeret filerne til Fotograf. Hvis du ikke ved hvordan du gør det, kan du stadig køre Fotograf; det er bare lidt mere besværligt: når der i vejledningen står at du skal indtaste noget i kommandolinjen, så skal du indtaste lidt mere end der står. Hvis der f.eks. står at du skal indtaste: java Fotograf<retur> så skal du i stedet indtaste java -classpath <stien til Fotograf> Fotograf<retur> hvor du i stedet for <stien til Fotograf> skal indtaste den rigtige sti, uden de kantede parenteser. På et Windowssystem kunne kommandoen f.eks. se sådan her ud: java -classpath c:\programmer\fotograf Fotograf<retur> I resten af vejledningen er udganspunktet at din classpath er sat som beskrevet. 29

30 7.4 Afvikling af programmet Når du har lavet en scenbeskrivelse og gemt den i en fil (f.eks scene.xml), så er du klar til at køre Fotograf. Hvis den aktive mappe i din kommandofortolker er samme mappe som din scenebeskrivelse ligger i, så kører du Fotograf ved at skrive: java Fotograf scene.xml<retur> Fotograf vil nu gå i gang med at læse din scenebeksrivelse. Hvis scenebeskrivelsen er korrekt, så vil der for hvert pilotsyn blive lavet et billede med samme navn som pilotsynet, påhæftet endelsen.ppm. Disse billeder vil blive lagt i samme mappe som Fotograf. 7.5 Meddelelser Når Fotograf kører, så vil det løbende udskrive meddelelser om hvor langt det er kommet. Mens den laver et billede vil den udskrive en stjerne for hver 10% den bliver færdig med; så kan du se at programmet stadig arbejder Fejlmeddelelser Fotograf er lavet så det kan hjælpe dig med at finde fejl i din scenebeskrivelse. Hvis Fotograf opdager en fejl, så udskriver den så præcis en meddelelse den kan om, hvad fejlen er. Hvis du f.eks. har glemt at give solen en farve, så vil Fotograf skrive: Indlæser scene.xml... Der er en fejl i scene.xml: (scene)->solen (sol)->farve En farve skal angives Programmet afsluttes De ting, der står i parentes, er navne på tags og det der står før parentesen er det id du har givet tagget. Så ud fra ovenstående meddelelse, så ved du at du skal kigge efter et <sol>-tag, hvor id et er solen. 30

31 Litteratur [1] DIKU Flight Simulator april [2] Eric Jul. Erics OOD. marts [3] Søren Sjørup. Pilotsyn. maj [4] Perdita Stevens. Using UML: Software engineering with objects and components. Addison-Wesley, updated edition edition,

32 A Klasser og arv 32

33 B Associationsdiagram C CRC-kort Herunder følger vores CRC-kort i alfabetisk rækkefølge. 33

34 C.1 Element 34

35 C.2 Fotograf 35

36 C.3 Kamera 36

37 C.4 Kugle 37

38 C.5 Mesh 38

39 C.6 Plan 39

40 C.7 Punkt3D 40

41 C.8 Scene 41

42 C.9 Sceneopstiller 42

43 C.10 Sol 43

44 C.11 Stråle 44

45 C.12 Trekant 45

46 C.13 XMLParseError 46

47 D Grænseflader I det følgende vil vi gennemgå klasserne og deres grænseflader i alfabetisk rækkefølge. D.1 Klassen Element Element er en abstrakt klasse, der repræsenterer en form i scenen, f.eks. en kugle. Den implementerer en enkelt metode til bestemmelse af farven i et punkt, da denne metode vil være ens for alle former. Denne struktur understøtter ikke textures, da formerne ikke har mulighed for at give en bestemt farve alt efter hvor de skærer den relevante stråle. Bump-mapping er muligt, da klassen forudsætter at underklasserne implementerer findnormal. Følgende er klassens grænseflade: Color findfarve( Stråle stråle ) Returnerer farven i det punkt, hvor den givne stråle rammer elementet. Hvis strålen ikke rammer, returneres null. abstract Punkt3D findnormal( Stråle stråle ) Denne metode skal returnere normalvektoren til overfladen i det punkt, hvor den givne stråle rammer. abstract Punkt3D findskæring( Stråle stråle ) Metoden skal returnere det nærmeste skæringspunkt med den givne stråle. Hvis der ikke er en skæring skal null returneres. abstract Color hentfarve( ) Skal returnere elementets grundfarve. D.2 Klassen Fotograf Fotograf-klassen er hovedklassen i programmet. Den indeholder programmets eneste s- tatiske metode, der opretter en ny fotograf. Hvis andre programmer skal bruge dette modul som et undermodul, så kan der ses bort fra main-metoden og man kan blot oprette en fotograf og give ham navnet på filen med modelbeskrivelsen. Fotograf har grænsefladen: static void main( String[] args ) Metoden undersøger om der er ét argument. I bekræftende fald oprettes en ny fotograf, der får dette ene argument. Hvis der ikke er præcis ét argument udskrives en fejlmeddelelse og programmet afsluttes. void udføropgave( String filnavn ) Fotografen producerer de billeder som er beskrevet i modelbeskrivelsen i filen filnavn. 47

48 D.3 Klassen Kamera Dette er vores implementation af grænsefladen KameraI. Kameraet sporer kun en stråle for hver pixel og alialisering er derfor sandsynlig. Grænsefladen er (se også KameraI afs. D.4): Kamera( Punkt3D øjepunkt, Punkt3D stedpunkt, Punkt3D vandret, Punkt3D lodret, int opløsning_vandret, int opløsning_lodret, SceneI scene, String navn ) Konstruktør, der opretter et kamera efter de principper, der er diskuteret i afsnit Når tagbillede kaldes, tager kameraet et billede af scene og gemmer det i navn påhæftet endelsen.ppm. void tagbillede( ) Se KameraI for en beskrivelse. D.4 Klassen KameraI Dette er et interface for et kamera. Et kameras opgave er at tage et billede af en model og at gemme dette billede i en fil. void tagbillede( ) Fortæller kameraet at det skal lave og gemme sit billede. D.5 Klassen Kugle Kugle er en underklasse af Element og er en repræsentation af en kugleform. Se Element for en forklaring af metoderne i klassen - kun konstruktøren beskrives her. Kugle( Punkt3D centrum, double radius, Color farve ) Konstruktør, der opretter en kugle med argumenterne som karakteristika. Punkt3D findnormal( Stråle stråle ) Se Element. Punkt3D findskæring( Stråle stråle ) Se Element. Punkt3D hentfarve( ) Se Element. 48

49 D.6 Klassen Mesh Mesh repræsenterer en samling af trekanter, dvs. det er en form, der kan placeres i en scene og den er derfor en underklasse af Element. Mesh er konstrueret, så det kan opbygges efterhånden som punkter og trekanter bliver indlæst. En beskrivelse af de metoder, der er pålagt af Element skal ses i den klasses beskrivelse. Resten er beskrevet her: Mesh( Color farve ) Laver et tomt mesh med den angivne farve. Punkt3D findnormal( Stråle stråle ) Se Element. Punkt3D findskæring( Stråle stråle ) Se Element. Punkt3D hentfarve( ) Se Element. void tilføjpunkt( int id, Punkt3D punkt ) Tilføjer punktet til meshet. id er den reference som bruges ved tilføjtrekant. Metoden kaster fejlen XMLParseError, hvis der allerede er et punkt med samme koordinatsæt. void tilføjtrekant( int p1, int p2, int p3 ) Tilføjer en trekant til meshet, hvor p1, p2 og p3 refererer til punkter tilføjet med metoden tilføjpunkt. D.7 Klassen Plan Plan er en underklasse af Element og er en repræsentation af en plan. Da Trekant skal bruge plankonstanterne, er der public-adgangsmetoder til disse. Se desuden Element for en forklaring af visse af metoderne i klassen - resten beskrives her. Plan( Punkt3D stedpunkt, Punkt3D vektor1, Punkt3D vektor2, Color farve ) Opretter den plan der udspændes af de to vektorer ud fra stedpunktet. Punkt3D findnormal( Stråle stråle ) Se Element. Punkt3D findskæring( Stråle stråle ) Se Element. Punkt3D hentfarve( ) Se Element. 49

50 double henta( ) Returnerer koefficienten A i den generelle ligning for en plan: Ax + By + Cz + D = 0. double hentb( ) Returnerer koefficienten B i den generelle ligning for en plan: Ax+By +Cz +D = 0. double hentc( ) Returnerer koefficienten C i den generelle ligning for en plan: Ax + By + Cz + D = 0. double hentd( ) Returnerer koefficienten D i den generelle ligning for en plan: Ax+By +Cz +D = 0. D.8 Klassen Punkt3D Som navnet antyder er der her tale om en klasse, der repræsenterer et punkt eller en vektor i tre dimensioner. Klassen skelner ikke selv mellem punkt og vektor, da det i forskellige sammenhænge kan være praktisk at betragte et koordinatsæt det ene eller det andet. Metoderne i klassen implementerer forskellige ofte brugte udregninger fra rumgeometrien. Klassens grænseflade er som følger: Punkt3D( double x, double y, double z ) Konstruktør til oprettelse af et punkt/vektor med de givne koordinater. boolean ernulvektor( ) Returnerer true, hvis vektoren er nulvektoren ellers false. boolean erens( Punkt3D punkt ) Sammenligner punkt s koordinater med egne koordinater og returnerer true hvis de er ens, ellers false. double findcos( Punkt3D punkt ) Returnerer cosinus til vinklen mellem de to vektorer. Bruger sammenhængen A B = cos ( (A, B) ) A B. Hvis en af vektorerne er nulvektoren returneres NaN. Punkt3D finddif( Punkt3D punkt ) Returnerer differensvektoren. double finddist( Punkt3D punkt ) Returnerer afstanden til det givne punkt. Punkt3D findkrydsprodukt( Punkt3D punkt ) Returnerer krydsproduktet med den givne vektor. 50

51 double findlængde( ) Returnerer vektorens længde. double findskalarprodukt( Punkt3D punkt ) Returnerer skalarproduktet med punkt. Punkt3D findskaleret( double t ) Returnerer denne vektor skaleret med t. Punkt3D findsum( Punkt3D punkt ) Returnerer sumvektoren. Punkt3D findvektortil( Punkt3D punkt ) Returnerer vektoren fra dette punkt til det givne punkt. double hentx( ) Returnerer punktets x-koordinat. double henty( ) Returnerer punktets y-koordinat. double hentz( ) Returnerer punktets z-koordinat. void saetx( double x ) Sætter punktets x-koordinat. void saety( double y ) Sætter punktets y-koordinat. void saetz( double z ) Sætter punktets z-koordinat. D.9 Klassen Scene Scene er vores implementation af grænsefladen SceneI. Den implementere en simpel strålesporingsmodel, med kun én lyskilde. Konstruktionen af Scene er sådan, at man kan tilføje de forskellige dele efterhånden som de bliver indlæst fra modelbeskrivelsen. Kun konstruktøren beskrives her, da de andre metoder opfylder kontrakten fra grænsefladen SceneI. Scene( ) Konstruktør, der opretter en tom scene. void findfarve( Stråle stråle ) Se SceneI. 51

52 void tilføj( Element e ) Se SceneI. void tilføjsol( Sol s ) Se SceneI. D.10 Klassen SceneI Denne grænseflade beskriver, de metoder en scene skal implementere. void findfarve( Stråle stråle ) Metoden skal bruge strålesporing til at bestemme strålens farve. stråle s farve sættes til den fundne farve. void tilføj( Element e ) Skal tilføje elementet til scenen. void tilføjsol( Sol s ) Skal tilføje den givne sol til scenen. Kan kaste XMLParseError hvis scenen ikke kan håndtere flere sole. D.11 Klassen Sceneopstiller Denne klasse står for at oversætte en modelbeskrivelse til den interne repræsentation af scene og kameraer. Dvs. den kobler XML til den interne repræsentation. Klassen er - som foreslået i opgaveteksten [1, app. C] - baseret på XMLReadWrite af Søren Sjørup (zoren@diku.dk). Følgende er klassens interface: Sceneopstiller( ) Konstruktør, der opretter en ny sceneopstiller. Vector opstilscene( String filnavn ) Indlæser modelbeskrivelsen af filnavn og opretter den tilsvarende scene. Den Vector, der returneres, indeholder de KameraI-objekter der var defineret i filen. D.12 Klassen Sol Solen repræsenteres af denne klasse. Sol( Punkt3D position, Color farve ) Konstruktør, der opretter en ny sol med den givne position og farve. Stråle belys( Punkt3D punkt ) Returnerer en stråle, med samme farve og udgangspunkt som solen, og med retning mod det givne punkt. Kaster NullPointerException hvis punkt er null. 52

53 D.13 Klassen Stråle Repræsentation af en stråle - i form af et begyndelsespunkt, en retningsvektor og en farve - med følgende grænseflade: Stråle( Punkt3D start, Punkt3D retning, Color farve ) Konstruktør, der laver en ny stråle med de givne attributter. Color hentfarve( ) Returnerer strålens farve. Punkt3D hentretning( ) Returnerer strålens retning. Punkt3D hentstart( ) Returnerer strålens begyndelsespunkt. void saetfarve( Color farve ) Sætter strålens farve til den givne. void saetretning( Punkt3D retning ) Sætter strålens retning til den givne. void saetstart( Punkt3D start ) Sætter strålens begyndelsespunkt til det givne. D.14 Klassen Trekant Trekant er en underklasse af Element og er en repræsentation af en trekant ;-). Se Element for en forklaring af metoderne i klassen - kun konstruktøren beskrives her. Trekan( Punkt3D p1, Punkt3D p2, Punkt3D p3 ) Punkt3D findnormal( Stråle stråle ) Se Element. Punkt3D findskæring( Stråle stråle ) Se Element. Punkt3D hentfarve( ) Se Element. D.15 Klassen XMLParseError Instanser af denne klasse kastes når der opstår en fejl pga. modelbeskrivelsen. XMLParseError( String fejl ) Konstruktør, der opretter en ny XMLParseError med fejl som meddelelse. 53

54 E Kildekode Dette appendiks indeholder kildekoden til det udviklede program. Klasserne er listet i alfabetisk rækkefølge. Se forsiden for en reference til kildekoden i elektronisk form på DIKU s system. E.1 Element.java / Denne k l a s s e r e p r æ s e n t e r e r e t element ( en form ) i en scene. Klassen implementerer en g e n e r i s k f a r v e u d r e g n i n g s f u n k t i o n findfarve. Underklasser er a n s v a r l i g e f o r at implementere en funktion, der kan f o r t æ l l e om en s t r å l e skærer e l e m e n t e t og hvor d e t s k e r. Endvidere s k a l u n d e r k l a s s e r kunne g i v e normalvektoren t i l e t skæringspunkt med en g i v e n s t r å l e. / import java. awt. Color ; public abstract class Element { // Farveudregningsfunktion, der f i n d e r f a r v e n i // skæringen med en g i v e n s o l s t r å l e // //Metoden f o r u d s æ t t e r at s o l s t r å l e n skærer e l e m e n t e t public Color f i n d F a r v e ( S t r å l e s o l s t r å l e ) { // Find normalvektoren i s k æ r i n g s p u n k t e t Punkt3D normal = findnormal ( s o l s t r å l e ) ; // Hvis der i k k e er en normal, er d e t f o r d i // s o l s t r å l e n i k k e rammer e l e m e n t e t // > ingen f a r v e i f ( normal == null ) return null ; // Find c o s i n u s t i l komplimentærvinklen // mellem s o l s t r å l e n og normalvektoren double cosv = Math. abs ( normal. findcos ( s o l s t r å l e. hentretning ( ) ) ) ; // Find f a r v e n i p u n k t e t Color f a r v e = hentfarve ( ) ; // Skab den nye f a r v e return new Color ( ( int ) ( cosv f a r v e. getred ( ) ), ( int ) ( cosv f a r v e. getgreen ( ) ), ( int ) ( cosv f a r v e. getblue ( ) ) ) ; // A b s t r a c t metode der s k a l bestemme normalvektoren // t i l s k æ r i n g s p u n k t e t med en g i v e n s t r å l e protected abstract Punkt3D findnormal ( S t r å l e s o l s t r å l e ) ; //Metoden f o r t æ l l e r om den g i v n e s t r å l e rammer 54

55 // e l e m e n t e t og e v t. hvor. // // n u l l r e t u r n e r e s h v i s der i k k e er en skæring public abstract Punkt3D findskæring ( S t r å l e s t r å l e ) ; // A b s t r a c t a c c e s s o r t i l e l e m e n t e t s f a r v e protected abstract Color hentfarve ( ) ; E.2 Fotograf.java / Fotografens opgave er at modtage opgaver og s ø r g e f o r at de b l i v e r u d f ø r t / import java. u t i l. Vector ; import java. u t i l. Enumeration ; public class Fot og ra f { // I n d g a n g s f u n k t i o n public s t a t i c void main ( S t r i n g [ ] a r g s ) { // Uforudsete u n d t a g e l s e r s k a l f a n g e s inden de når brugeren try { // Ét argument i f ( a r g s. l e n g t h!= 1) { System. out. p r i n t l n ( "\nder s k a l være e t argument! " ) ; System. out. p r i n t l n ( "\nprogrammet a f s l u t t e s " ) ; System. e x i t ( 1 ) ; return ; (new Fotograf ( ) ). udføropgave ( a r g s [ 0 ] ) ; catch ( Throwable t ) { System. out. p r i n t l n ( "\nder opstod en ukendt f e j l! " ) ; S t r i n g f e j l = t. g e t L o c a l i z e d M e s s a g e ( ) ; i f ( f e j l!= null ) System. out. p r i n t l n ( " f e j l b e s k e d : "+ f e j l ) ; System. out. p r i n t l n ( "\nprogrammet a f s l u t t e s " ) ; System. e x i t ( 1 ) ; / Metode der f å r f o t o g r a f e n t i l at udføre opgaven i f i l e n f i l n a v n / public void udføropgave ( S t r i n g f i l n a v n ) { //Gør scenen k l a r Vector kameraer = (new S c e n e o p s t i l l e r ( ) ). o p s t i l S c e n e ( f i l n a v n ) ; //Tag b i l l e d e r n e for ( Enumeration e = kameraer. elements ( ) ; e. hasmoreelements ( ) ; ) { ( ( KameraI ) e. nextelement ( ) ). t a g B i l l e d e ( ) ; E.3 Kamera.java / Repræsenterer e t kamera i form a f e t øjepunkt, en f i l m 55

56 ( s t e d p u n k t og vandret og l o d r e t v e k t o r ), en o p l ø s n i n g og navnet på b i l l e d e t. S t e d p u n k t e t i k o n s t r u k t ø r e n er n e d e r s t e v e n s t r e hjørne, men i den i n t e r n e r e p r æ s e n t a t i o n er d e t ø v e r s t e v e n s t r e. Lodret v e k t o r e n b l i v e r vendt t i l v a r e n d e. Se KameraI / import java. awt. Color ; import java. i o. IOException ; import K2. ; public class Kamera implements KameraI { // Konstruktør // // Forudsætter k o r r e k t e argumenter! public Kamera ( Punkt3D øjepunkt, Punkt3D stedpunkt, Punkt3D vandret, Punkt3D l o d r e t, int opløsning_vandret, int o p l ø s n i n g _ l o d r e t, SceneI scene, S t r i n g navn ) { this. øjepunkt = øjepunkt ; this. stedpunkt = stedpunkt. findsum ( l o d r e t ) ; // Vektorerne t i l p a s s e s h e n h o l d s v i s bredden // og højden a f e t r e f e r e n c e f e l t this. vandret = vandret. f i n d S k a l e r e t ( 1. 0 / opløsning_vandret ) ; this. l o d r e t = l o d r e t. f i n d S k a l e r e t ( 1.0/ o p l ø s n i n g _ l o d r e t ) ; this. opløsning_ vandret = opløsning_ vandret ; this. o p l ø s n i n g _ l o d r e t = o p l ø s n i n g _ l o d r e t ; this. navn = navn ; this. s c e n e = s c e n e ; / Metode der opbygger e t b i l l e d e a f scenen og gemmer d e t i en f i l / public void t a g B i l l e d e ( ) { // Udskriv respons t i l brugeren System. out. p r i n t ( "\ nlaver b i l l e d e \""+hentnavn ()+" \ " : " ) ; System. out. f l u s h ( ) ; // Opret e t kanvas t i l at tegne på Kanvas kanvas = new Kanvas ( hentopløsning_ lodret ( ), hentopløsning_vandret ( ), Color.BLACK ) ; //Vi v i l u d s k r i v e l øbende respons ( pr. 10 procent ) //Hvor mange p i x e l s er en procent? int procent = hentopløsning_vandret ( ) hentopløsning_ lodret ( ) / 1 0 ; int o k P i x e l s = 0 ; // a n t a l f æ r d i g e p i x e l s int okprocent = 0 ; // o k P i x e l s i procent int tmp_int = 0 ; // a r b e j d s v a r // Skyd en s t r å l e pr. p i x e l ind i scenen for ( int i = hentopløsning_vandret ( ) ; i > 0 ; i ) { for ( int j = hentopløsning_ lodret ( ) ; j > 0 ; j ) { // Find midten a f r e f e r e n c e f e l t e t Punkt3D vandskal = hentvandret ( ). f i n d S k a l e r e t ( i 0. 5 ) ; Punkt3D l o d S k a l = hentlodret ( ). f i n d S k a l e r e t ( j 0. 5 ) ; Punkt3D midt = vandskal. findsum ( l o d S k a l. findsum ( hentstedpunkt ( ) ) ) ; 56

57 //Lav en s t r å l e f r a ø j e p u n k t e t gennem p u n k t e t S t r å l e s t r å l e = new S t r å l e ( hentøjepunkt ( ), hentøjepunkt ( ). f i n d V e k t o r T i l ( midt ), null ) ; //Send s t r å l e n t i l scenen s c e n e. f i n d F a r v e ( s t r å l e ) ; //Sæt f a r v e n på p i x e l e n kanvas. s e t P i x e l ( i 1, j 1, s t r å l e. hentfarve ( ) ) ; // Respons tmp_int = ++o k P i x e l s / procent ; // f i n procent f æ r d i g i f ( tmp_int > okprocent ) { okprocent = tmp_int ; System. out. p r i n t ( " " ) ; System. out. f l u s h ( ) ; System. out. p r i n t l n ( " f æ r d i g " ) ; System. out. f l u s h ( ) ; //Gem b i l l e d e t try { kanvas. skrivppm ( navn ) ; // Fotæl at b i l l e d e t er gemt System. out. p r i n t l n ( "\ t \""+hentnavn ()+"\" e r gemt i " +hentnavn ()+". ppm" ) ; System. out. f l u s h ( ) ; catch ( IOException e ) { // Fortæl brugeren om problemet og a f s l u t System. out. p r i n t l n ( "\nder opstod en f e j l under " +" s k r i v n i n g e n a f f i l e n "+hentnavn ()+". ppm" ) ; System. out. p r i n t l n ( "\nprogrammet a f s l u t t e s. " ) ; System. e x i t ( 1 ) ; // Accessors og mutators private Punkt3D hentøjepunkt ( ) { return øjepunkt ; private Punkt3D hentstedpunkt ( ) { return stedpunkt ; private Punkt3D hentvandret ( ) { return vandret ; private Punkt3D hentlodret ( ) { return l o d r e t ; private int hentopløsning_vandret ( ) { return opløsning_ vandret ; private int hentopløsning_ lodret ( ) { return o p l ø s n i n g _ l o d r e t ; private S t r i n g hentnavn ( ) { return navn ; private SceneI hentscene ( ) { return s c e n e ; 57

58 // P r i v a t e a t t r i b u t t e r private Punkt3D øjepunkt = null ; private Punkt3D stedpunkt = null ; private Punkt3D vandret = null, l o d r e t = null ; private int opløsning_vandret, o p l ø s n i n g _ l o d r e t ; private S t r i n g navn = null ; private SceneI s c e n e ; E.4 KameraI.java / D e f i n e r e r i n t e r f a c e t f o r e t kamera. Et kamera s k a l t a g e e t b i l l e d e a f en scene og gemme d e t i en f i l / public interface KameraI { / Metoden der f å r kameraet t i l at t a g e e t b i l l e d e og gemme d e t / public void t a g B i l l e d e ( ) ; E.5 Kugle.java / Repræsenterer en k u g l e i form a f e t centrum, en r a d i u s og en f a r v e. O b j e k t e t s t å r f o r at beregne skæring med s t r å l e r samt b e r e g n i n g a f normalvektorer i skæringer. / import java. awt. Color ; public class Kugle extends Element { // Konstruktør // // Forudsætter g y l d i g e ( i k k e n u l l ) argumenter public Kugle ( Punkt3D centrum, double radius, Color f a r v e ) { this. centrum = centrum ; this. r a d i u s = r a d i u s ; this. f a r v e = f a r v e ; / Metode t i l at bestemme en normalvektoren i e t skæringspunkt med en s t r å l e. Hvis der i k k e er e t skæringspunkt, så er der ingen normal > n u l l / protected Punkt3D findnormal ( S t r å l e s o l s t r å l e ) { // f i n d skæring Punkt3D skæring = findskæring ( s o l s t r å l e ) ; // Hvis der i k k e er en skæring, er der ingen normal i f ( skæring == null ) return null ; 58

59 Punkt3D normal = hentcentrum ( ). f i n d D i f ( skæring ) ; return normal ; / Metode, der f i n d e r en e v t. skæring med en g i v e n s t r å l e. n u l l r e t u r n e r e s, h v i s der ingen skæring er / public Punkt3D findskæring ( S t r å l e s t r å l e ) { // Hvis s t r å l e n i k k e er d e f i n e r e t, skærer den // i k k e k u g l e n i f ( s t r å l e == null ) return null ; // Skæringspunkter f i n d e s med udgangspunkt // i at s t r å l e n er en l i n j e // Find k o e f f i c i e n t e r n e i 2. g r a d s l i g n i n g e n Punkt3D s t r å l e R e t = s t r å l e. hentretning ( ), s t r å l e S t a r t = s t r å l e. h e n t S t a r t ( ), d i f V e k t o r = s t r å l e S t a r t. f i n d D i f ( hentcentrum ( ) ) ; ; double xdif = d i f V e k t o r. hentx ( ) ; // x_0 x_c double ydif = d i f V e k t o r. henty ( ) ; // y_0 y_c double z D i f = d i f V e k t o r. hentz ( ) ; // z_0 z_c double a = Math. pow( s t r å l e R e t. hentx ( ), 2. 0 ) + Math. pow( s t r å l e R e t. henty ( ), 2. 0 ) + Math. pow( s t r å l e R e t. hentz ( ), 2. 0 ) ; double b = 2 ( s t r å l e R e t. hentx ( ) xdif + s t r å l e R e t. henty ( ) ydif + s t r å l e R e t. hentz ( ) z D i f ) ; double c = Math. pow( xdif, 2. 0 ) + Math. pow( ydif, 2. 0 ) + Math. pow( zdif, 2. 0 ) Math. pow( hentradius ( ), 2. 0 ) ; //Udregn d i s k r i m i n a n t e n d double d = Math. pow(b, 2. 0 ) 4 a c ; //Er der en l ø s n i n g? i f ( d < 0. 0 ) // nope return null ; else {// én e l l e r to l ø s n i n g e r // beregn begge t værdier double t1 = ( b + Math. s q r t ( d ) ) / (2 a ) ; double t2 = ( b Math. s q r t ( d ) ) / (2 a ) ; // Find den nærmeste, der er en d e l a f s t r å l e n double t ; i f ( t1 < 0. 0 && t2 < 0. 0 ) // begge er u b r u g e l i g e return null ; else i f ( t1 < 0. 0 ) // t1 er u b r u g e l i g t = t2 ; else i f ( t2 < 0. 0 ) // t2 er u b r u g e l i g t = t1 ; else // t a g den nærmeste t = ( t1 < t2 )? t1 : t2 ; return new Punkt3D ( s t r å l e S t a r t. hentx()+ t s t r å l e R e t. hentx ( ), s t r å l e S t a r t. henty()+ t s t r å l e R e t. henty ( ), 59

60 s t r å l e S t a r t. hentz ()+ t s t r å l e R e t. hentz ( ) ) ; // Accessors og mutators private double hentradius ( ) { return r a d i u s ; private Punkt3D hentcentrum ( ) { return centrum ; protected Color hentfarve ( ) { return f a r v e ; // P r i v a t e a t t r i b u t t e r private Punkt3D centrum = null ; private Color f a r v e = null ; private double r a d i u s ; E.6 Mesh.java / Repræsenterer e t t r e k a n t s g i t t e r. / import java. awt. Color ; import java. u t i l. Comparator ; import java. u t i l. I t e r a t o r ; import java. u t i l. Vector ; import java. u t i l. TreeMap ; import java. u t i l. Enumeration ; public class Mesh extends Element { // Konstruktør // // Forudsætter g y l d i g t ( i k k e n u l l ) argument public Mesh ( Color f a r v e ) { this. f a r v e = f a r v e ; / Metode, der f i n d e r en e v t. skæring med en g i v e n s t r å l e. n u l l r e t u r n e r e s, h v i s der ingen skæring er Metoden s æ t t e r e n d i v e r e v a r i a b l e n sidstramt t i l den s i d s t ramte t r e k a n t f o r e f f e k t i v i t e t / public Punkt3D findskæring ( S t r å l e s t r å l e ) { //Gennemløb t r e k a n t e r n e og f i n d e v t. nærmeste skæring Punkt3D skæring = null ; Trekant t r e k a n t = null ; Punkt3D tmpsk = null ; // Arbejdsvar double s k D i s t = 0 ; // Afstand mellem s t r å l e og skæring for ( Enumeration e = t r e k a n t e r. elements ( ) ; e. hasmoreelements ( ) ; tmpsk = null ) { t r e k a n t = ( Trekant ) e. nextelement ( ) ; tmpsk = t r e k a n t. findskæring ( s t r å l e ) ; // Find den skæring der s k a l gemmes 60

61 i f ( ( tmpsk == null && skæring == null ) tmpsk == null ) continue ; else i f ( skæring == null ( s k D i s t > s t r å l e. h e n t S t a r t ( ). f i n d D i s t ( tmpsk ) ) ) { skæring = tmpsk ; s k D i s t = s t r å l e. h e n t S t a r t ( ). f i n d D i s t ( skæring ) ; sidstramt = t r e k a n t ; return skæring ; / Metode t i l at bestemme en normalvektoren i e t skæringspunkt med en s t r å l e. Hvis der i k k e er e t skæringspunkt, så er der ingen normal > n u l l Metoden f o r u d s æ t t e r at der er s k e t en forudgående s t r å l s p o r i n g / protected Punkt3D findnormal ( S t r å l e s o l s t r å l e ) { return sidstramt. findnormal ( s o l s t r å l e ) ; / Metode t i l at t i l f ø j e punkter t i l meshet / public void t i l f ø j P u n k t ( int id, Punkt3D punkt ) throws XMLParseError { // Tjek at e t punkt magen t i l i k k e er d e f i n e r e t I t e r a t o r i t = punkter. v a l u e s ( ). i t e r a t o r ( ) ; Punkt3D p = null ; while ( i t. hasnext ( ) ) { p = ( Punkt3D ) i t. next ( ) ; i f ( p. erens ( punkt ) ) throw new XMLParseError ( i d + " ( punkt )\ n\ t \ tder e r to ens punkter " ) ; punkter. put (new I n t e g e r ( i d ), punkt ) ; / Metode t i l at t i l f ø j e t r e k a n t e r t i l meshet. Det f o r u d s æ t t e r at punkterne er i n d l æ s t e l l e r s k a s t e s / public void t i l f ø j T r e k a n t ( int punkt1, int punkt2, int punkt3 ) throws XMLParseError { Punkt3D p1 = ( Punkt3D ) punkter. get (new I n t e g e r ( punkt1 ) ) ; Punkt3D p2 = ( Punkt3D ) punkter. get (new I n t e g e r ( punkt2 ) ) ; Punkt3D p3 = ( Punkt3D ) punkter. get (new I n t e g e r ( punkt3 ) ) ; // Sørg f o r v a l i d e punkter S t r i n g e r r o r = null ; int errorp = 0 ; i f ( p1 == null ) { e r r o r = "p1" ; errorp = punkt1 ; i f ( p2 == null ) { e r r o r = "p2" ; errorp = punkt2 ; 61

62 i f ( p3 == null ) { e r r o r = "p3" ; errorp = punkt3 ; i f ( e r r o r!= null ) throw new XMLParseError ( e r r o r+"\n\ t \ t U d e f i n e r e t punkt : "+errorp ) ; t r e k a n t e r. add (new Trekant ( p1, p2, p3, hentfarve ( ) ) ) ; // Accessors og mutators protected Color hentfarve ( ) { return f a r v e ; // P r i v a t e a t t r i b u t t e r private Color f a r v e = null ; private TreeMap punkter = new TreeMap (new Comparator ( ) { public int compare ( Object t a l 1, Object t a l 2 ) { int t1 = ( ( I n t e g e r ) t a l 1 ). intvalue ( ) ; int t2 = ( ( I n t e g e r ) t a l 2 ). intvalue ( ) ; i f ( t1 < t2 ) return 1; else i f ( t1 > t2 ) return 1 ; else return 0 ; ) ; private Vector t r e k a n t e r = new Vector ( ) ; private Trekant sidstramt = null ; E.7 Plan.java / Repræsenterer en plan i form a f de f i r e k o e f f i c i e n t e r (A, B, C og D) i den g e n e r e l l e l i g n i n g f o r en plan i R3 Ax+By+Cz+D = 0 O b j e k t e t s t å r f o r at beregne skæring med s t r å l e r samt b e r e g n i n g a f normalvektorer i skæringer. / import java. awt. Color ; public class Plan extends Element { // Konstruktør // // Opretter en plan ud f r a e t stedpunkt, // to r e t n i n g s v e k t o r e r og en f a r v e public Plan ( Punkt3D stedpunkt, Punkt3D vektor1, Punkt3D vektor2, Color f a r v e ) { this. f a r v e = f a r v e ; //Gem en normalvektor normal = vektor1. findkrydsprodukt ( vektor2 ) ; //De f i r e k o e f f i c i e n t e r bestemmes // Først udregnes de t r e determinanter (A, B og C) A = vektor1. henty ( ) vektor2. hentz ( ) vektor1. hentz ( ) vektor2. henty ( ) ; 62

63 B = vektor1. hentz ( ) vektor2. hentx ( ) vektor1. hentx ( ) vektor2. hentz ( ) ; C = vektor1. hentx ( ) vektor2. henty ( ) vektor1. henty ( ) vektor2. hentx ( ) ; D = A stedpunkt. hentx ( ) B stedpunkt. henty ( ) C stedpunkt. hentz ( ) ; / Metode, der f i n d e r en e v t. skæring med en g i v e n s t r å l e. n u l l r e t u r n e r e s, h v i s der ingen skæring er / public Punkt3D findskæring ( S t r å l e s t r å l e ) { // Hvis s t r å l e n i k k e er d e f i n e r e t, skærer den // i k k e planen i f ( s t r å l e == null ) return null ; Punkt3D s t r å l e R e t = s t r å l e. hentretning ( ), s t r å l e S t a r t = s t r å l e. h e n t S t a r t ( ) ; //Udregn nævneren i l i g n i n g e n f o r t ( opgaven s. 9 ) double nævner = henta ( ) s t r å l e R e t. hentx ( ) + hentb ( ) s t r å l e R e t. henty ( ) + hentc ( ) s t r å l e R e t. hentz ( ) ; // Hvis nævneren er nul, så er planen // og s t r å l e n p a r a l l e l l e > ingen skæring i f ( nævner == 0. 0 ) return null ; double t = ( henta ( ) s t r å l e S t a r t. hentx ( ) + hentb ( ) s t r å l e S t a r t. henty ( ) + hentc ( ) s t r å l e S t a r t. hentz ( ) + hentd ( ) ) / nævner ; // t < 0 > s t r å l e n skærer i k k e planen i f ( t < 0. 0 ) return null ; return s t r å l e S t a r t. findsum ( s t r å l e R e t. f i n d S k a l e r e t ( t ) ) ; / Metode t i l at bestemme en normalvektoren i e t skæringspunkt med en s t r å l e. Hvis der i k k e er e t skæringspunkt, så er der ingen normal > n u l l / protected Punkt3D findnormal ( S t r å l e s o l s t r å l e ) { return normal ; // Accessors og mutators protected Color hentfarve ( ) { return f a r v e ; public double henta ( ) { 63

64 return A; public double hentb ( ) { return B; public double hentc ( ) { return C; public double hentd ( ) { return D; // P r i v a t e a t t r i b u t t e r private Color f a r v e = null ; private Punkt3D normal = null ; private double A, B, C, D; E.8 Punkt3D.java / Repræsenterer e t punkt (/ s t e d v e k t o r ) i t r e dimensioner S t i l l e r d i v e r s e r e l a t e r e d e o p e r a t i o n e r t i l r å d i g h e d / public class Punkt3D { // Konstruktør public Punkt3D ( double x, double y, double z ) { saetx ( x ) ; saety ( y ) ; saetz ( z ) ; //Metode der f o r t æ l l e r om de to punkter er ens public boolean erens ( Punkt3D punkt ) { return f i n d D i f ( punkt ). ernulvektor ( ) ; //Metode der f o r t æ l l e r om d e t er n u l v e k t o r e n public boolean ernulvektor ( ) { return ( hentx ( ) == 0 && henty ( ) == 0 && hentz ( ) == 0 ) ; //Metode t i l at beregne cos t i l v i n k l e n mellem // denne og en anden v e k t o r public double findcos ( Punkt3D punkt ) { return f i n d S k a l a r p r o d u k t ( punkt ) / ( findlængde ( ) punkt. findlængde ( ) ) ; //Metode t i l at f i n d e d i f f e r e n s e n mellem // d e t t e punkt og en andet punkt public Punkt3D f i n d D i f ( Punkt3D punkt ) { return new Punkt3D ( hentx ( ) punkt. hentx ( ), henty ( ) punkt. henty ( ), hentz ( ) punkt. hentz ( ) ) ; //Metode t i l at f i n d e a f s t a n d e n mellem // d e t t e punkt og en andet punkt public double f i n d D i s t ( Punkt3D punkt ) { return this. f i n d V e k t o r T i l ( punkt ). findlængde ( ) ; 64

65 //Metode t i l at beregne k r y d s p r o d u k t e t a f denne // og en anden v e k t o r public Punkt3D findkrydsprodukt ( Punkt3D punkt ) { return new Punkt3D ( henty ( ) punkt. hentz ( ) hentz ( ) punkt. henty ( ), hentz ( ) punkt. hentx ( ) hentx ( ) punkt. hentz ( ), hentx ( ) punkt. henty ( ) henty ( ) punkt. hentx ( ) ) ; //Metode t i l at beregne længden a f ( sted ) v e k t o r e n public double findlængde ( ) { return Math. s q r t (Math. pow( hentx ( ), 2. 0 ) + Math. pow( henty ( ), 2. 0 ) + Math. pow( hentz ( ), 2. 0 ) ) ; //Metode t i l at beregne s k a l a r p r o d u k t e t a f denne // og en anden v e k t o r public double f i n d S k a l a r p r o d u k t ( Punkt3D punkt ) { return hentx ( ) punkt. hentx ( ) + henty ( ) punkt. henty ( ) + hentz ( ) punkt. hentz ( ) ; //Metode der beregner p r o d u k t e t a f // denne v e k t o r og s k a l a r e n t public Punkt3D f i n d S k a l e r e t ( double t ) { return new Punkt3D ( t hentx ( ), t henty ( ), t hentz ( ) ) ; //Metode t i l at f i n d e summen a f d e t t e punkt // ( v e k t o r ) og e t andet punkt ( v e k t o r ) public Punkt3D findsum ( Punkt3D punkt ) { return new Punkt3D ( punkt. hentx ( ) + hentx ( ), punkt. henty ( ) + henty ( ), punkt. hentz ( ) + hentz ( ) ) ; //Metode t i l at f i n d e v e k t o r e n f r a d e t t e punkt // t i l e t andet punkt public Punkt3D f i n d V e k t o r T i l ( Punkt3D punkt ) { return punkt. f i n d D i f ( this ) ; public double hentx ( ) { return x ; public double henty ( ) { return y ; public double hentz ( ) { return z ; // Accessors og mutators public void saetx ( double x ) { this. x = x ; public void saety ( double y ) { this. y = y ; public void saetz ( double z ) { 65

66 this. z = z ; //De e g e n t l i g e k o o r d i n a t e r private double x, y, z ; E.9 Scene.java / Repræsenterer en scene med elementer og l y s k i l d e r. Scenen er a n s v a r l i g f o r at f o r e t a g e f a r v e b e s t e m m e l s e / s t r å l e s p o r i n g. Se grænsefladen SceneI / import java. awt. Color ; import java. u t i l. Vector ; import java. u t i l. Enumeration ; public class Scene implements SceneI { / T i l f ø j element t i l scenen / public void t i l f ø j ( Element e ) { elementer. add ( e ) ; / Sæt s o l e n / public void t i l f ø j S o l ( Sol s ) throws XMLParseError { i f ( s o l!= null ) //kun en s o l er t i l l a d t throw new XMLParseError ( "\n\ t \tkun én s o l e r t i l l a d t " ) ; s o l = s ; / Farvebestemmelsesfunktion / public void f i n d F a r v e ( S t r å l e s t r å l e ) { //en ikke d e f i n e r e t s t r å l e har i k k e f a r v e i f ( s t r å l e == null ) return ; // Ingen s o l > ingen f a r v e ; ) i f ( hentsol ( ) == null ) { s t r å l e. saetfarve ( Color.BLACK) ; return ; // Find nærmeste skæring og d e t t i l s v a r e n d e element Punkt3D skæring = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; Element element = s t r å l e s p o r i n g ( s t r å l e, skæring ) ; // Ingen skæring > ingen f a r v e i f ( skæring == null ) { s t r å l e. saetfarve ( Color.BLACK) ; return ; // Find ud a f om s o l e n s l y s rammer p u n k t e t 66

67 S t r å l e s o l s t r å l e = hentsol ( ). b e l y s ( skæring ) ; Punkt3D solskæring = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; i f ( s t r å l e s p o r i n g ( s o l s t r å l e, s o l S k æ r i n g ) == null ) { // s o l e n s t r å l e n ramte i k k e noget ( p r æ c i s i o n s f e j l ) // > ingen f a r v e s t r å l e. saetfarve ( Color.BLACK) ; return ; i f (! sammenlign ( skæring, solskæring ) ) { // s t r å l e n ramte noget andet s t r å l e. saetfarve ( Color.BLACK) ; return ; // Find f a r v e n s t r å l e. saetfarve ( element. f i n d F a r v e ( s o l s t r å l e ) ) ; / S t r å l e s p o r e r e n Returnerer d e t ramte element og s æ t t e r skæring t i l s k æ r i n g s p u n k t e t / private Element s t r å l e s p o r i n g ( S t r å l e s t r å l e, Punkt3D skæring ) { // Find nærmeste skæring og d e t t i l s v a r e n d e element Element element = null ; Punkt3D skær = null ; Element tmpel = null ; // Arbejdsvar Punkt3D tmpsk = null ; // Arbejdsvar double s k D i s t = 0 ; // Afstand mellem s t r å l e og skæring Enumeration e = hentelementer ( ). elements ( ) ; for ( ; e. hasmoreelements ( ) ; tmpsk = null ) { tmpel = ( Element ) e. nextelement ( ) ; tmpsk = tmpel. findskæring ( s t r å l e ) ; // Find den skæring der s k a l gemmes i f ( ( tmpsk == null && skær == null ) tmpsk == null ) continue ; else i f ( skær == null ( s k D i s t > s t r å l e. h e n t S t a r t ( ). f i n d D i s t ( tmpsk ) ) ) { skær = tmpsk ; s k D i s t = s t r å l e. h e n t S t a r t ( ). f i n d D i s t ( skær ) ; element = tmpel ; // Kopier e t e v t. skæringspunkt i f ( skær!= null ) { skæring. saetx ( skær. hentx ( ) ) ; skæring. saety ( skær. henty ( ) ) ; skæring. saetz ( skær. hentz ( ) ) ; return element ; / Metode t i l at sammenligne om to punkter er t i l s t r æ k k e l i g ens / private boolean sammenlign ( Punkt3D p1, Punkt3D p2 ) { double OKDif = 1e 3; // Acceptabel a f s t a n d 67

68 Punkt3D d i f = p2. f i n d D i f ( p1 ) ; return ( d i f. findlængde ( ) < OKDif )? true : f a l s e ; // Accessors og mutators private Vector hentelementer ( ) { return elementer ; private Sol hentsol ( ) { return s o l ; // P r i v a t e a t t r i b u t t e r private Vector elementer = new Vector ( ) ; private Sol s o l = null ; E.10 SceneI.java / I n t e r f a c e der d e f i n e r e r en scenes g r æ n s e f l a d e / public interface SceneI { //Metode t i l at t i l f ø j e elementer // t i l scenen public void t i l f ø j ( Element e ) ; //Metode t i l at t i l f ø j e l y s k i l d e r //Kan k a s t e XMLParseError h v i s scenen har // begrænsninger på a n t a l l e t a f l y s k i l d e r public void t i l f ø j S o l ( Sol s ) throws XMLParseError ; // S t r å l e s p o r i n g s f u n k t i o n, der bestemmer // ( og s æ t t e r ) f a r v e n på den modtagne s t r å l e public void f i n d F a r v e ( S t r å l e s t r å l e ) ; E.11 Sceneopstiller.java / S c e n e o p t i l l e r e n s opgave er at o v e r s æ t t e en XML b e s k r i v e l s e t i l den i n t e r n e r e p r æ s e n t a t i o n Er l a v e t ud f r a XMLReadWrite a f Søren Sjørup ( zoren@diku. dk ) F e j l m e d d e l e l s e r b l i v e r o p b y g g e t h i e r a k i s k, dvs. de b l i v e r o p b y g g e t b a g f r a og f å r t i l f ø j e t information ved b a c k t r a c k i n g. / import javax. xml. p a r s e r s. DocumentBuilder ; import javax. xml. p a r s e r s. DocumentBuilderFactory ; import org. xml. sax. SAXException ; import java. awt. Color ; import java. i o. F i l e ; import java. u t i l. Vector ; import org. w3c. dom. ; public class S c e n e o p s t i l l e r { 68

69 / Metode t i l at o p s t i l l e en scene ud f r a en XML f i l. Der r e t u r n e r e s en Vector med KameraI o b j e k t e r / public Vector o p s t i l S c e n e ( S t r i n g f i l n a v n ){ // Vektor t i l kamera Vector kameraer = null ; // Scenen SceneI s c e n e = null ; // Fortæl brugeren hvor l a n g t processen er System. out. p r i n t ( "\ nindlæser "+f i l n a v n+"... " ) ; System. out. f l u s h ( ) ; // Indlæs f i l e n org. w3c. dom. Element r o o t=parsexml ( f i l n a v n ) ; // Tjek at dokumentet i n d e h o l d e r en rod og at den hedder scene i f ( r o o t==null ) { System. out. p r i n t l n ( "\n\nder e r en f e j l i "+f i l n a v n+" : " ) ; System. out. p r i n t l n ( "\ t ( s c e n e )\ n\ t \ tder s k a l være e t scene tag " ) ; System. out. p r i n t l n ( "\nprogrammet a f s l u t t e s " ) ; System. e x i t ( 1 ) ; i f (! r o o t. getnodename ( ). e q u a l s ( " s c e n e " ) ) { System. out. p r i n t l n ( "\n\nder e r en f e j l i "+f i l n a v n+" : " ) ; System. out. p r i n t l n ( "\ t ( s c e n e )\ n\ t \troden s k a l være s c e n e ( i k k e " +r o o t. getnodename()+" ) " ) ; System. out. p r i n t l n ( "\nprogrammet a f s l u t t e s " ) ; System. e x i t ( 1 ) ; try{ //Lav i n t e r n e r e p r æ s e n t a t i o n a f scenen s c e n e = o v e r s æ t T i l S c e n e ( r o o t ) ; //Og gør kameraerne k l a r kameraer = klargørkameraer ( root, s c e n e ) ; catch ( XMLParseError excep ){ System. out. p r i n t l n ( "\n\nder e r en f e j l i "+f i l n a v n+" : " ) ; System. out. p r i n t l n ( "\ t ( s c e n e) >"+excep. getmessage ( ) ) ; System. out. p r i n t l n ( "\nprogrammet a f s l u t t e s " ) ; System. e x i t ( 1 ) ; // Fortæl brugeren hvor l a n g t processen er System. out. p r i n t l n ( " f æ r d i g " ) ; System. out. f l u s h ( ) ; return kameraer ; private s t a t i c org. w3c. dom. Element parsexml ( S t r i n g f i l n a v n ){ org. w3c. dom. Element r o o t=null ; Document document ; DocumentBuilderFactory f a c t o r y =DocumentBuilderFactory. newinstance ( ) ; try { DocumentBuilder b u i l d e r = f a c t o r y. newdocumentbuilder ( ) ; document = b u i l d e r. p a r s e ( new F i l e ( f i l n a v n ) ) ; r o o t=document. getdocumentelement ( ) ; catch ( SAXException e ) { // s y n t a k t i s k f e j l System. out. p r i n t l n ( "\n\nder e r en s y n t a k t i s k f e j l i "+f i l n a v n ) ; 69

70 System. out. p r i n t l n ( "\nprogrammet a f s l u t t e s " ) ; System. e x i t ( 1 ) ; catch ( Throwable e ) { System. out. p r i n t l n ( "\n\nder opstod en f e j l i f o r s ø g e t på at læse "+f i l n a v n ) ; System. out. p r i n t l n ( "\nprogrammet a f s l u t t e s " ) ; System. e x i t ( 1 ) ; return r o o t ; // læs XML indeholdende scenedata // og l a v Kamera o b j e k t e r private Vector klargørkameraer ( org. w3c. dom. Element root, SceneI s c e n e ) throws XMLParseError { Vector kameraer = new Vector ( ) ; NodeList n l ; n l=r o o t. getelementsbytagname ( " p i l o t s y n " ) ; // hent p i l o t s y n t a g s for ( int i = 0 ; i <n l. getlength ( ) ; i ++){ o v e r s æ t P i l o t s y n ( n l. item ( i ), kameraer, s c e n e ) ; // kør return kameraer ; // læs XML indeholdende scendata // og opbyg i n t e r n scene private SceneI o v e r s æ t T i l S c e n e ( org. w3c. dom. Element r o o t ) throws XMLParseError { SceneI s c e n e = new Scene ( ) ; NodeList n l ; n l=r o o t. getelementsbytagname ( " s o l " ) ; // hent for ( int i = 0 ; i <n l. getlength ( ) ; i ++){ oversætsol ( n l. item ( i ), s c e n e ) ; s o l t a g s n l=r o o t. getelementsbytagname ( " kugle " ) ; // hent for ( int i = 0 ; i <n l. getlength ( ) ; i ++){ oversætkugle ( n l. item ( i ), s c e n e ) ; n l=r o o t. getelementsbytagname ( "mesh" ) ; // hent for ( int i = 0 ; i <n l. getlength ( ) ; i ++){ oversætmesh ( n l. item ( i ), s c e n e ) ; n l=r o o t. getelementsbytagname ( " plan " ) ; // hent for ( int i = 0 ; i <n l. getlength ( ) ; i ++){ oversætplan ( n l. item ( i ), s c e n e ) ; kugle t a g s mesh t a g s plan t a g s return s c e n e ; //Metode t i l at i n dlæse e t punkt g i v e t e t map a f a t t r i b u t t e r. // Returværdien er p u n k t e t s i d. // Punkt ændres t i l d e t i n d l æ s t e. private S t r i n g oversætpunktfrannm (NamedNodeMap nnm, Punkt3D punkt ) throws XMLParseError { 70

71 S t r i n g i d = null ; try { i d = nnm. getnameditem ( " i d " ). getnodevalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( punkt )\ n\ t \ tet i d s k a l a n g i v e s f o r punktet " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( punkt )\ n\ t \ t i d e t e r a n g i v e t f o r k e r t " ) ; try { double x=(new Double (nnm. getnameditem ( "x" ). getnodevalue ( ) ) ). doublevalue ( ) ; punkt. saetx ( x ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( punkt) >x"+ "\n\ t \ten x værdi s k a l a n g i v e s f o r punktet " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( i d+" ( punkt) >x"+ "\n\ t \ tx værdien e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( i d+" ( punkt) >x"+ "\n\ t \ tx værdien s k a l være e t t a l " ) ; try { double y=(new Double (nnm. getnameditem ( "y" ). getnodevalue ( ) ) ). doublevalue ( ) ; punkt. saety ( y ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( punkt) >y"+ "\n\ t \ten y værdi s k a l a n g i v e s f o r punktet " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( i d+" ( punkt) >y"+ "\n\ t \ ty værdien e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( i d+" ( punkt) >y"+ "\n\ t \ ty værdien s k a l være e t t a l " ) ; try { double z=(new Double (nnm. getnameditem ( " z " ). getnodevalue ( ) ) ). doublevalue ( ) ; punkt. saetz ( z ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( punkt) >z "+ "\n\ t \ten z værdi s k a l a n g i v e s f o r punktet " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( i d+" ( punkt) >z "+ "\n\ t \ tz værdien e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( i d+" ( punkt) >z "+ "\n\ t \ tz værdien s k a l være e t t a l " ) ; return i d ; // l æ s e r en t r e k a n t g i v e t e t map a f a t t r i b u t t e r // og i n d s æ t t e r i meshet private void oversættrekantfrannm (NamedNodeMap nnm, Mesh mesh ) throws XMLParseError { int p1 = 0, p2 = 0, p3 = 0 ; try { p1=(new I n t e g e r (nnm. getnameditem ( "p1" ). getnodevalue ( ) ) ). intvalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( t r e k a n t) >p1\n\ t \ tpunktet s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( t r e k a n t) >p1\n\ t \ tpunktet e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( " ( t r e k a n t) >p1\n\ t \ tværdien s k a l være e t t a l " ) ; try { 71

72 p2=(new I n t e g e r (nnm. getnameditem ( "p2" ). getnodevalue ( ) ) ). intvalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( t r e k a n t) >p2\n\ t \ tpunktet s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( t r e k a n t) >p2\n\ t \ tpunktet e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( " ( t r e k a n t) >p2\n\ t \ tværdien s k a l være e t t a l " ) ; try { p3=(new I n t e g e r (nnm. getnameditem ( "p3" ). getnodevalue ( ) ) ). intvalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( t r e k a n t) >p3\n\ t \ tpunktet s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( t r e k a n t) >p3\n\ t \ tpunktet e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( " ( t r e k a n t) >p3\n\ t \ tværdien s k a l være e t t a l " ) ; // Punkterne må i k k e være ens i f ( p1 == p2 p2 == p3 p3 == p1 ) throw new XMLParseError ( " ( t r e k a n t )\ n\ t \ ttrekanter må i k k e have to ens punkter " ) ; mesh. t i l f ø j T r e k a n t ( p1, p2, p3 ) ; //Metode t i l at i n dlæse en f a r v e g i v e t e t map a f a t t r i b u t t e r private Color oversætfarvefrannm (NamedNodeMap nnm) throws XMLParseError { int r = 0, g = 0, b = 0 ; try { r=(new I n t e g e r (nnm. getnameditem ( " r " ). getnodevalue ( ) ) ). intvalue ( ) ; //kun værdier i i n t e r v a l l e t [ 0 ; ] i f ( r < < r ) throw new XMLParseError ( " f a r v e >r "+ "\n\ t \ tr værdien s k a l være i i n t e r v a l l e t [ 0 ; ] " ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " f a r v e >r \n\ t \ten r værdi s k a l a n g i v e s f o r f a r v e n " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " f a r v e >r \n\ t \ tr værdien e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( " f a r v e >r \n\ t \ tr værdien s k a l være e t h e l t a l " ) ; try { g=(new I n t e g e r (nnm. getnameditem ( "g" ). getnodevalue ( ) ) ). intvalue ( ) ; //kun værdier i i n t e r v a l l e t [ 0 ; ] i f ( g < < g ) throw new XMLParseError ( " f a r v e >g"+ "\n\ t \ tg værdien s k a l være i i n t e r v a l l e t [ 0 ; ] " ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " f a r v e >g\n\ t \ten g værdi s k a l a n g i v e s f o r f a r v e n " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " f a r v e >g\n\ t \ tg værdien e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( " f a r v e >g\n\ t \ tg værdien s k a l være e t h e l t a l " ) ; try { b=(new I n t e g e r (nnm. getnameditem ( "b" ). getnodevalue ( ) ) ). intvalue ( ) ; //kun værdier i i n t e r v a l l e t [ 0 ; ] i f ( b < < b ) throw new XMLParseError ( " f a r v e >b"+ "\n\ t \tb værdien s k a l være i i n t e r v a l l e t [ 0 ; ] " ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " f a r v e >b\n\ t \ten b værdi s k a l a n g i v e s f o r f a r v e n " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " f a r v e >b\n\ t \tb værdien e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( " f a r v e >b\n\ t \tb værdien s k a l være e t h e l t a l " ) ; 72

73 return new Color ( r, g, b ) ; // l æ s e r en k u g l e g i v e t en xml knude // og t i l f ø j e r t i l scenen private void oversætkugle ( Node nn, SceneI s c e n e ) throws XMLParseError{ NamedNodeMap nnm=nn. g e t A t t r i b u t e s ( ) ; S t r i n g i d = null ; try { i d=nnm. getnameditem ( " i d " ). getnodevalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( kugle )\ n\ t \ tet i d s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( kugle )\ n\ t \ t i d e t e r a n g i v e t f o r k e r t " ) ; NodeList n l = null ; Color f a r v e = null ; try { n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " f a r v e " ) ; f a r v e = oversætfarvefrannm ( n l. item ( 0 ). g e t A t t r i b u t e s ( ) ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( kugle) >f a r v e \n\ t \ tfarve s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( i d+" ( kugle) >f a r v e \n\ t \ tfarven e r a n g i v e t f o r k e r t " ) ; catch ( Throwable e ) { // F e j l i f a r v e throw new XMLParseError ( i d+" ( kugle) >"+e. getmessage ( ) ) ; double r = 0 ; try { n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " r a d i u s " ) ; r=new Double ( n l. item ( 0 ). g e t A t t r i b u t e s ( ). getnameditem ( " r " ). getnodevalue ( ) ). doublevalue ( ) ; //kun p o s i t i v e værdier i f ( r <= 0) throw new XMLParseError ( i d+" ( kugle) >r a d i u s \n\ t \ t "+ " Radius s k a l være e t p o s i t i v " ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( kugle) >r a d i u s \n\ t \ten r a d i u s s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( i d+" ( kugle) >r a d i u s \n\ t \ tradius e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( i d+" ( kugle) >r a d i u s \n\ t \ tradius s k a l være e t t a l " ) ; NamedNodeMap punktnnm = null ; Punkt3D p o s i t i o n = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; try { n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " punkt " ) ; punktnnm=n l. item ( 0 ). g e t A t t r i b u t e s ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) {// i k k e a n g i v e t throw new XMLParseError ( i d+" ( kugle) >centrum ( punkt ) "+ "\n\ t \tcentrum s k a l a n g i v e s " ) ; S t r i n g pid = null ; try { pid = oversætpunktfrannm ( punktnnm, p o s i t i o n ) ; catch ( XMLParseError e ) { // f e j l i p u n k t e t throw new XMLParseError ( i d+" ( kugle) >"+e. getmessage ( ) ) ; 73

74 // Tjek at p u n k t e t hed p o s i t i o n i f (! pid. e q u a l s ( " centrum " ) ) throw new XMLParseError ( i d+" ( kugle) >(punkt )\ n\ t \ tukendt punkt "+pid ) ; s c e n e. t i l f ø j (new Kugle ( p o s i t i o n, r, f a r v e ) ) ; // l æ s e r en plan g i v e t en xml knude // og i n d s æ t t e r i scene private void oversætplan ( Node nn, SceneI s c e n e ) throws XMLParseError{ NamedNodeMap nnm=nn. g e t A t t r i b u t e s ( ) ; S t r i n g i d = null ; try { i d=nnm. getnameditem ( " i d " ). getnodevalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( plan )\ n\ t \ tet i d s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( plan )\ n\ t \ t i d e t e r a n g i v e t f o r k e r t " ) ; NodeList n l = null ; Color f a r v e = null ; try { n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " f a r v e " ) ; f a r v e = oversætfarvefrannm ( n l. item ( 0 ). g e t A t t r i b u t e s ( ) ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( plan) >f a r v e \n\ t \ tfarve s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( i d+" ( plan) >f a r v e \n\ t \ tfarven e r a n g i v e t f o r k e r t " ) ; catch ( Throwable e ) { // F e j l i f a r v e throw new XMLParseError ( i d+" ( plan) >"+e. getmessage ( ) ) ; Punkt3D stedpunkt = null, r e t n i n g 1 = null, r e t n i n g 2 = null ; n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " punkt " ) ; for ( int i = 0 ; i <n l. getlength ( ) ; i ++){// læs punkterne der udspænder planen NamedNodeMap punktnnm=n l. item ( i ). g e t A t t r i b u t e s ( ) ; S t r i n g navn = null ; try { navn=punktnnm. getnameditem ( " i d " ). getnodevalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( plan) >(punkt )\ n\ t \ tet i d s k a l a n g i v e s " ) ; i f ( navn. e q u a l s ( " stedpunkt " ) ) try { stedpunkt = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; oversætpunktfrannm ( punktnnm, stedpunkt ) ; catch ( XMLParseError e ) { throw new XMLParseError ( i d+" ( plan) >"+e. getmessage ( ) ) ; 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 " ) ) try { r e t n i n g 1 = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; oversætpunktfrannm ( punktnnm, r e t n i n g 1 ) ; catch ( XMLParseError e ) { throw new XMLParseError ( i d+" ( plan) >"+e. getmessage ( ) ) ; 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 " ) ) try { 74

75 r e t n i n g 2 = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; oversætpunktfrannm ( punktnnm, r e t n i n g 2 ) ; catch ( XMLParseError e ) { throw new XMLParseError ( i d+" ( plan) >"+e. getmessage ( ) ) ; else throw new XMLParseError ( i d+" ( plan) >"+navn+" ( punkt ) "+ "\n\ t \ tukendt punkt " ) ; // Tjek at de t r e punkter er a n g i v e t i f ( stedpunkt == null ) throw new XMLParseError ( i d+" ( plan) >stedpunkt ( punkt ) "+ "\n\ t \ tstedpunkt s k a l a n g i v e s " ) ; i f ( r e t n i n g 1 == null ) throw new XMLParseError ( i d+" ( plan) >r e t n i n g s v e k t o r 1 ( punkt ) "+ "\n\ t \ t R e t n i n g s v e k t o r 1 s k a l a n g i v e s " ) ; i f ( r e t n i n g 2 == null ) throw new XMLParseError ( i d+" ( plan) >r e t n i n g s v e k t o r 2 ( punkt ) "+ "\n\ t \ t R e t n i n g s v e k t o r 2 s k a l a n g i v e s " ) ; // t j e k at de to v e k t o r e r i k k e er n u l v e k t o r e n i f ( r e t n i n g 1. ernulvektor ( ) ) throw new XMLParseError ( i d+" ( plan) >r e t n i n g s v e k t o r 1 ( punkt ) "+ "\n\ t \ t R e t n i n g s v e k t o r e r må i k k e være n u l v e k t o r e n " ) ; i f ( r e t n i n g 2. ernulvektor ( ) ) throw new XMLParseError ( i d+" ( plan) >r e t n i n g s v e k t o r 2 ( punkt ) "+ "\n\ t \ t R e t n i n g s v e k t o r e r må i k k e være n u l v e k t o r e n " ) ; // t j e k at de to v e k t o r e r i k k e er p a r a l l e l l e // r2 = r e t n i n g 1 Punkt3D r2 = r e t n i n g 2. f i n d S k a l e r e t ( r e t n i n g 1. findlængde ( ) / r e t n i n g 2. findlængde ( ) ) ; i f ( r2. f i n d D i f ( r e t n i n g 1 ). findlængde ( ) == 0. 0 r2. f i n d S k a l e r e t ( 1. 0 ). f i n d D i f ( r e t n i n g 1 ). findlængde ( ) == 0. 0 ) throw new XMLParseError ( i d+" ( plan ) "+ "\n\ t \ t R e t n i n g s v e k t o r e r n e må i k k e være p a r a l e l l e " ) ; s c e n e. t i l f ø j (new Plan ( stedpunkt, r e t n i n g 1, r e t n i n g 2, f a r v e ) ) ; // l æ s e r e t mesh g i v e t en xml knude // og t i l f ø j e r t i l scenen private void oversætmesh ( Node nn, SceneI s c e n e ) throws XMLParseError{ NamedNodeMap nnm=nn. g e t A t t r i b u t e s ( ) ; S t r i n g i d = null ; try { i d=nnm. getnameditem ( " i d " ). getnodevalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( mesh )\ n\ t \ tet i d s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( mesh )\ n\ t \ t i d e t e r a n g i v e t f o r k e r t " ) ; try { NodeList n l = null ; Color f a r v e = null ; try { n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " f a r v e " ) ; f a r v e = oversætfarvefrannm ( n l. item ( 0 ). g e t A t t r i b u t e s ( ) ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " f a r v e \n\ t \ tfarve s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " f a r v e \n\ t \ tfarven e r a n g i v e t f o r k e r t " ) ; 75

76 // f e j l i f a r v e b l i v e r f a n g e t på næste niveau // Opret mesh Mesh mesh = new Mesh ( f a r v e ) ; n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " punkter " ) ; i f ( n l. getlength ( ) == 0) throw new XMLParseError ( " ( punkter )\ n\ t \ tpunkter s k a l a n g i v e s " ) ; for ( int i = 0 ; i <n l. getlength ( ) ; i ++){// læs punkterne i mesh nnm=n l. item ( i ). g e t A t t r i b u t e s ( ) ; int antal_ punkter = 0 ; try { antal_ punkter=( new I n t e g e r (nnm. getnameditem ( " antal_punkter " ). getnodevalue ( ) ) ). intvalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( punkter) >antal_ punkter "+ "\n\ t \ t A n t a l l e t a f punkter s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( punkter) >antal_ punkter "+ "\n\ t \ t A n t a l l e t a f punkter e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) {// i k k e e t t a l throw new XMLParseError ( " ( punkter) >antal_ punkter "+ "\n\ t \ t A n t a l l e t a f punkter s k a l være e t h e l t a l " ) ; // antal_punkter s k a l være s t ø r r e end e l l e r l i g nul i f ( antal_ punkter < 0) throw new XMLParseError ( " ( punkter) >antal_ punkter "+ "\n\ t \ t A n t a l l e t a f punkter kan i k k e være n e g a t i v t " ) ; i f ( nn. getnodetype()==node.element_node){ NodeList l o c a l n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " punkt " ) ; // antal_punkter s k a l være r i g t i g i f ( antal_punkter!= l o c a l n l. getlength ( ) ) throw new XMLParseError ( " ( punkter) >antal_ punkter "+ "\n\ t \ t A n t a l l e t a f punkter s k a l matche antal_punkter " ) ; for ( int j = 0 ; j<l o c a l n l. getlength ( ) ; j ++){ // o p r e t p u n k t e t Punkt3D punkt = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; nnm=l o c a l n l. item ( j ). g e t A t t r i b u t e s ( ) ; int nr = 0 ; try { nr=(new I n t e g e r (nnm. getnameditem ( " i d " ). getnodevalue ( ) ) ). intvalue ( ) ; // oversæt d e t oversætpunktfrannm (nnm, punkt ) ; // t i l f ø j t i l meshet mesh. t i l f ø j P u n k t ( nr, punkt ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( punkter) >(punkt ) "+ "\n\ t \ tet i d s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( punkter) >(punkt ) "+ "\n\ t \ t i d e t e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) {// i d e t er i k k e e t t a l throw new XMLParseError ( " ( punkter) >(punkt ) "+ "\n\ t \ t i d e t s k a l være e t t a l " ) ; catch ( Throwable e ) { // F e j l i punkt throw new XMLParseError ( " ( punkter) >"+e. getmessage ( ) ) ; n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " t r e k a n t e r " ) ; 76

77 i f ( n l. getlength ( ) == 0) throw new XMLParseError ( " ( t r e k a n t e r )\ n\ t \ ttrekanter s k a l a n g i v e s " ) ; for ( int i = 0 ; i <n l. getlength ( ) ; i ++){// læs t r e k a n t e r n e i mesh nnm=n l. item ( i ). g e t A t t r i b u t e s ( ) ; int a n t a l _ t r e k a n t e r = 0 ; try { a n t a l _ t r e k a n t e r =( new I n t e g e r (nnm. getnameditem ( " a n t a l _ t r e k a n t e r " ). getnodevalue ( ) ) ). intvalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( t r e k a n t e r) >a n t a l _ t r e k a n t e r "+ "\n\ t \ t A n t a l l e t a f t r e k a n t e r s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( t r e k a n t e r) >a n t a l _ t r e k a n t e r "+ "\n\ t \ t A n t a l l e t a f t r e k a n t e r e r a n g i v e t f o r k e r t " ) ; catch ( NumberFormatException e ) {// i k k e e t t a l throw new XMLParseError ( " ( t r e k a n t e r) >a n t a l _ t r e k a n t e r "+ "\n\ t \ t A n t a l l e t a f t r e k a n t e r s k a l være e t h e l t a l " ) ; // a n t a l _ t r e k a n t e r s k a l være s t ø r r e end e l l e r l i g nul i f ( a n t a l _ t r e k a n t e r < 0) throw new XMLParseError ( " ( t r e k a n t e r) >a n t a l _ t r e k a n t e r "+ "\n\ t \ t A n t a l l e t a f t r e k a n t e r kan i k k e være n e g a t i v t " ) ; i f ( nn. getnodetype()==node.element_node){ NodeList l o c a l n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " t r e k a n t " ) ; // a n t a l _ t r e k a n t e r s k a l være r i g t i g i f ( a n t a l _ t r e k a n t e r!= l o c a l n l. getlength ( ) ) throw new XMLParseError ( " ( t r e k a n t e r) >a n t a l _ t r e k a n t e r "+ "\n\ t \ t A n t a l l e t a f t r e k a n t e r s k a l matche a n t a l _ t r e k a n t e r " ) ; for ( int j = 0 ; j<l o c a l n l. getlength ( ) ; j ++){ nnm=l o c a l n l. item ( j ). g e t A t t r i b u t e s ( ) ; // Oversæt og indsæt t r e k a n t e n i meshet try { oversættrekantfrannm (nnm, mesh ) ; catch ( XMLParseError e ) { throw new XMLParseError ( " ( t r e k a n t e r) >"+( j +1)+". ( t r e k a n t) >"+e. getmessage ( ) ) ; s c e n e. t i l f ø j ( mesh ) ; catch ( Throwable e ) { throw new XMLParseError ( i d+" ( mesh) >"+e. getmessage ( ) ) ; // l æ s e r e t p i l o t s y n g i v e t en xml knude // og t i l f ø j e r t i l kameraer private void o v e r s æ t P i l o t s y n ( Node nn, Vector kameraer, SceneI s c e n e ) throws XMLParseError { Node i t=nn. g e t F i r s t C h i l d ( ) ; int hoejde = 0 ; int bredde = 0 ; S t r i n g i d = null ; NamedNodeMap nnm=nn. g e t A t t r i b u t e s ( ) ; try { i d=nnm. getnameditem ( " i d " ). getnodevalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( p i l o t s y n ) >i d \n\ t \ tet i d s k a l a n g i v e s " ) ; 77

78 try { hoejde =(new I n t e g e r (nnm. getnameditem ( " hoejde " ). getnodevalue ( ) ) ). intvalue ( ) ; //kun p o s i t i v e værdier i f ( hoejde <= 0) throw new XMLParseError ( i d+" ( p i l o t s y n ) >hoejde "+ "\n\ t \ thøjde s k a l være s t ø r r e end nul " ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( p i l o t s y n ) >hoejde \n\ t \ thøjde s k a l a n g i v e s " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( i d+" ( p i l o t s y n ) >hoejde \n\ t \ thøjde s k a l være e t h e l t a l " ) ; try { bredde=(new I n t e g e r (nnm. getnameditem ( " bredde " ). getnodevalue ( ) ) ). intvalue ( ) ; //kun p o s i t i v e værdier i f ( bredde <= 0) throw new XMLParseError ( i d+" ( p i l o t s y n ) >bredde "+ "\n\ t \ tbredde s k a l være s t ø r r e end nul " ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( p i l o t s y n ) >bredde \n\ t \ tbredde s k a l a n g i v e s " ) ; catch ( NumberFormatException e ) { // i k k e e t t a l throw new XMLParseError ( i d+" ( p i l o t s y n ) >bredde \n\ t \ tbredde s k a l være e t h e l t a l " ) ; Punkt3D øjepunkt = null, stedpunkt = null, vandret = null, l o d r e t = null ; NodeList n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " punkt " ) ; for ( int i = 0 ; i <n l. getlength ( ) ; i ++){// læs punkterne i p i l o t s y n nnm=n l. item ( i ). g e t A t t r i b u t e s ( ) ; S t r i n g navn = null ; try { navn=nnm. getnameditem ( " i d " ). getnodevalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( p i l o t s y n ) >(punkt )\ n\ t \ tet i d s k a l a n g i v e s " ) ; i f ( navn. e q u a l s ( " p i l o t o e j e " ) ) try { øjepunkt = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; oversætpunktfrannm (nnm, øjepunkt ) ; catch ( XMLParseError e ) { throw new XMLParseError ( i d+" ( p i l o t s y n ) >"+e. getmessage ( ) ) ; else i f ( navn. e q u a l s ( " cockpitvindue_stedpunkt " ) ) try { stedpunkt = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; oversætpunktfrannm (nnm, stedpunkt ) ; catch ( XMLParseError e ) { throw new XMLParseError ( i d+" ( p i l o t s y n ) >"+e. getmessage ( ) ) ; else i f ( navn. e q u a l s ( " c o c k p i t v i n d u e _ l o d r e t " ) ) try { l o d r e t = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; oversætpunktfrannm (nnm, l o d r e t ) ; catch ( XMLParseError e ) { throw new XMLParseError ( i d+" ( p i l o t s y n ) >"+e. getmessage ( ) ) ; else i f ( navn. e q u a l s ( " cockpitvindue_vandret " ) ) try { 78

79 vandret = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; oversætpunktfrannm (nnm, vandret ) ; catch ( XMLParseError e ) { throw new XMLParseError ( i d+" ( p i l o t s y n ) >"+e. getmessage ( ) ) ; else throw new XMLParseError ( i d+" ( p i l o t s y n ) >"+navn+" ( punkt )\ n\ t \ tukendt punkt " ) ; // t j e k at de f i r e punkter er a n g i v e t i f ( øjepunkt == null ) throw new XMLParseError ( i d+" ( p i l o t s y n ) > p i l o t o e j e ( punkt ) "+ "\n\ t \ t P i l o t e n s øjepunkt s k a l a n g i v e s " ) ; i f ( stedpunkt == null ) throw new XMLParseError ( i d+" ( p i l o t s y n ) >cockpitvindue_stedpunkt ( punkt ) " +"\n\ t \ tstedpunkt s k a l a n g i v e s " ) ; i f ( vandret == null ) throw new XMLParseError ( i d+" ( p i l o t s y n ) >cockpitvindue_vandret ( punkt ) "+ "\n\ t \ tvandret s k a l a n g i v e s " ) ; i f ( l o d r e t == null ) throw new XMLParseError ( i d+" ( p i l o t s y n ) >c o c k p i t v i n d u e _ l o d r e t ( punkt ) " +"\n\ t \ tlodret s k a l a n g i v e s " ) ; // t j e k at de to v e k t o r e r i k k e er n u l v e k t o r e n i f ( vandret. ernulvektor ( ) ) throw new XMLParseError ( i d+" ( p i l o t s y n ) >cockpitvindue_vandret ( punkt ) " +"\n\ t \ tvandret må i k k e være n u l v e k t o r e n " ) ; i f ( l o d r e t. ernulvektor ( ) ) throw new XMLParseError ( i d+" ( p i l o t s y n ) >c o c k p i t v i n d u e _ l o d r e t ( punkt ) " +"\n\ t \ tlodret må i k k e være n u l v e k t o r e n " ) ; kameraer. add (new Kamera ( øjepunkt, stedpunkt, vandret, l o d r e t, bredde, hoejde, scene, i d ) ) ; // l æ s e r en s o l g i v e t en xml knude // og t i l f ø j e r t i l scene private void ov er sæ ts ol ( Node nn, SceneI s c e n e ) throws XMLParseError{ Color f a r v e = null ; Punkt3D p o s i t i o n = new Punkt3D ( 0. 0, 0. 0, 0. 0 ) ; NamedNodeMap nnm=nn. g e t A t t r i b u t e s ( ) ; S t r i n g i d = null ; try { i d=nnm. getnameditem ( " i d " ). getnodevalue ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( " ( s o l ) >i d \n\ t \ tet i d s k a l a n g i v e s " ) ; catch ( DOMException e ) { // T y p e f e j l throw new XMLParseError ( " ( s o l ) >i d \n\ t \ t i d e t e r a n g i v e t f o r k e r t " ) ; NodeList n l = null ; try { n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " f a r v e " ) ; f a r v e = oversætfarvefrannm ( n l. item ( 0 ). g e t A t t r i b u t e s ( ) ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) { // i k k e a n g i v e t throw new XMLParseError ( i d+" ( s o l ) >f a r v e \n\ t \ten f a r v e s k a l a n g i v e s " ) ; catch ( XMLParseError e ) { // f e j l i f a r v e n throw new XMLParseError ( i d+" ( s o l ) >"+e. getmessage ( ) ) ; 79

80 NamedNodeMap punktnnm = null ; try { n l =(( org. w3c. dom. Element ) nn ). getelementsbytagname ( " punkt " ) ; punktnnm=n l. item ( 0 ). g e t A t t r i b u t e s ( ) ; catch ( N u l l P o i n t e r E x c e p t i o n e ) {// i k k e a n g i v e t throw new XMLParseError ( i d+" ( s o l ) > p o s i t i o n ( punkt ) " +"\n\ t \ t P o s i t i o n e n s k a l a n g i v e s " ) ; S t r i n g pid = null ; try { pid = oversætpunktfrannm ( punktnnm, p o s i t i o n ) ; catch ( XMLParseError e ) { // f e j l i p u n k t e t throw new XMLParseError ( i d+" ( s o l ) >"+e. getmessage ( ) ) ; // Tjek at p u n k t e t hed p o s i t i o n i f (! pid. e q u a l s ( " p o s i t i o n " ) ) throw new XMLParseError ( i d+" ( s o l ) >(punkt )\ n\ t \ tukendt punkt "+pid ) ; // T i l f ø j s o l e n t i l scenen s c e n e. t i l f ø j S o l (new Sol ( p o s i t i o n, f a r v e ) ) ; E.12 Sol.java / Repræsenterer s o l e n i form a f dens p l a c e r i n g og f a r v e. Dens opgave er at l a v e l y s ; ) Kaster N u l l P o i n t e r E x c e p t i o n h v i s den f å r n u l l som argument t i l både k o n s t r u k t ø r e r og metoder, da de i k k e er meningsfulde værdier / import java. awt. Color ; public class Sol { // Konstruktør public Sol ( Punkt3D p l a c e r i n g, Color f a r v e ) { this. p l a c e r i n g = p l a c e r i n g ; this. f a r v e = f a r v e ; //Metode t i l at b e s k r i v e h v i l k e n s o l s t r å l e, // der l y s e r i r e t n i n g a f e t g i v e t punkt public S t r å l e b e l y s ( Punkt3D punkt ) { i f ( punkt == null ) // t j e k f o r u g y l d i g t argument throw new N u l l P o i n t e r E x c e p t i o n ( " Solen kan i k k e b e l y s e n u l l " ) ; // Find r e t n i n g s v e k t o r Punkt3D r e t n i n g = p l a c e r i n g. f i n d V e k t o r T i l ( punkt ) ; // Returner s o l s t r å l e n return new S t r å l e ( p l a c e r i n g, r e t n i n g, f a r v e ) ; private Punkt3D p l a c e r i n g = null ; private Color f a r v e = null ; 80

81 E.13 Stråle.java / Repræsenterer en s t r å l e i t r e dimensioner. D e f i n e r e s ved e t b e g y n d e l s e s p u n k t, en r e t n i n g s v e k t o r og en f a r v e. / import java. awt. Color ; public class S t r å l e { // Konstruktør public S t r å l e ( Punkt3D s t a r t, Punkt3D r e t n i n g, Color f a r v e ) { s a e t S t a r t ( s t a r t ) ; saetretning ( r e t n i n g ) ; saetfarve ( f a r v e ) ; // Accessors og mutators public void s a e t S t a r t ( Punkt3D s t a r t ) { this. s t a r t = s t a r t ; public Punkt3D h e n t S t a r t ( ) { return s t a r t ; public void saetretning ( Punkt3D r e t n i n g ) { this. r e t n i n g = r e t n i n g ; public Punkt3D hentretning ( ) { return r e t n i n g ; public void saetfarve ( Color f a r v e ) { this. f a r v e = f a r v e ; public Color hentfarve ( ) { return f a r v e ; // Stedpunkt private Punkt3D s t a r t = null ; // R e t n i n g s v e k t o r private Punkt3D r e t n i n g = null ; // Farve private Color f a r v e = null ; E.14 Trekant.java / Repræsenterer en t r e k a n t i form a f t r e punkter og en f a r v e / import java. awt. Color ; public class Trekant extends Element { // Konstruktør public Trekant ( Punkt3D punkt1, Punkt3D punkt2, Punkt3D punkt3, Color f a r v e ) { this. punkt1 = punkt1 ; this. punkt2 = punkt2 ; this. punkt3 = punkt3 ; this. f a r v e = f a r v e ; //Lav den plan som t r e k a n t e n l i g g e r i plan = new Plan ( punkt1, 81

82 punkt1. f i n d V e k t o r T i l ( punkt2 ), punkt1. f i n d V e k t o r T i l ( punkt3 ), f a r v e ) ; / Metode, der f i n d e r en e v t. skæring med en g i v e n s t r å l e. n u l l r e t u r n e r e s, h v i s der ingen skæring er / public Punkt3D findskæring ( S t r å l e s t r å l e ) { // Hvis s t r å l e n i k k e er d e f i n e r e t, skærer den // i k k e k u g l e n i f ( s t r å l e == null ) return null ; // Find e v t. skæring mellem t r e k a n t e n s plan // og s t r å l e Punkt3D planskæring = hentplan ( ). findskæring ( s t r å l e ) ; i f ( planskæring == null ) return null ; // ingen skæring //Hent planens k o e f f i c i e n t e r double A = Math. abs ( plan. henta ( ) ), B = Math. abs ( plan. hentb ( ) ), C = Math. abs ( plan. hentc ( ) ) ; // P r o j i c e r de t r e punkter og planskæringen // ind på den b e d s t e a f de t r e p l a n e r udspændt // a f akserne double [ ] p1 = new double [ 2 ], p2 = new double [ 2 ], p3 = new double [ 2 ], ps = new double [ 2 ] ; i f (A > B && A > C) { p1 [ 0 ] = punkt1. henty ( ) ; p1 [ 1 ] = punkt1. hentz ( ) ; p2 [ 0 ] = punkt2. henty ( ) ; p2 [ 1 ] = punkt2. hentz ( ) ; p3 [ 0 ] = punkt3. henty ( ) ; p3 [ 1 ] = punkt3. hentz ( ) ; ps [ 0 ] = planskæring. henty ( ) ; ps [ 1 ] = planskæring. hentz ( ) ; else i f (B > A && B > C) { p1 [ 0 ] = punkt1. hentx ( ) ; p1 [ 1 ] = punkt1. hentz ( ) ; p2 [ 0 ] = punkt2. hentx ( ) ; p2 [ 1 ] = punkt2. hentz ( ) ; p3 [ 0 ] = punkt3. hentx ( ) ; p3 [ 1 ] = punkt3. hentz ( ) ; ps [ 0 ] = planskæring. hentx ( ) ; ps [ 1 ] = planskæring. hentz ( ) ; else { p1 [ 0 ] = punkt1. hentx ( ) ; p1 [ 1 ] = punkt1. henty ( ) ; p2 [ 0 ] = punkt2. hentx ( ) ; p2 [ 1 ] = punkt2. henty ( ) ; p3 [ 0 ] = punkt3. hentx ( ) ; p3 [ 1 ] = punkt3. henty ( ) ; ps [ 0 ] = planskæring. hentx ( ) ; ps [ 1 ] = planskæring. henty ( ) ; 82

83 //Udregn de t r e determinanter ( opgave s. 1 0 ) double det1 = ( ps [0] p1 [ 0 ] ) ( p2 [1] p1 [ 1 ] ) ( ps [1] p1 [ 1 ] ) ( p2 [0] p1 [ 0 ] ) ; double det2 = ( ps [0] p2 [ 0 ] ) ( p3 [1] p2 [ 1 ] ) ( ps [1] p2 [ 1 ] ) ( p3 [0] p2 [ 0 ] ) ; double det3 = ( ps [0] p3 [ 0 ] ) ( p1 [1] p3 [ 1 ] ) ( ps [1] p3 [ 1 ] ) ( p1 [0] p3 [ 0 ] ) ; i f ( ( det1 >= 0. 0 && det2 >= 0. 0 && det3 >= 0. 0 ) ( det1 <= 0. 0 && det2 <= 0. 0 && det3 <= 0. 0 ) ) return planskæring ; return null ; / Metode t i l at bestemme en normalvektoren i e t skæringspunkt med en s t r å l e. Hvis der i k k e er e t skæringspunkt, så er der ingen normal > n u l l / protected Punkt3D findnormal ( S t r å l e s o l s t r å l e ) { //Lad planen om d e t grove ; ) return plan. findnormal ( s o l s t r å l e ) ; // Accessors og mutators protected Color hentfarve ( ) { return f a r v e ; private Plan hentplan ( ) { return plan ; // P r i v a t e a t t r i b u t t e r private Punkt3D punkt1 = null, punkt2 = null, punkt3 = null ; private Color f a r v e = null ; private Plan plan = null ; E.15 XMLParseError.java / Kastes ved f e j l der o p s t å r pga. f e j l i XML f i l e n ( s y n t a k t i s k e og semantiske ) / public class XMLParseError extends Throwable { XMLParseError ( S t r i n g s ){ super ( s ) ; 83

84 F Afprøvningsdata Dette appendiks indeholder inddata, forventet uddata samt faktisk uddata fra afprøvningerne. F.1 Afprøvning 1 Afprøvningen er kørsel af programmet med den obligatoriske lufthavn som inddata. Inddata Inddatafilen kan hentes på kursets hjemmeside: Forventet uddata Vi forventer, at der løbende bliver rapporteret om, hvilken proces programmet er i gang med. For billedgenerering forventer vi endvidere en respons om hvor langt processen er. Programmet skal generere et billede for hvert af de tre pilotsyn (syn1.ppm, syn2.ppm og syn3.ppm) og billederne skal have en opløsning på Billedet af pilotsyn syn2 skal ligne det der findes på adressen Faktisk uddata Se figur 1 for de resulterende billeder. I n d l æ s e r l u f t h a v n 2. xml... f æ r d i g Laver b i l l e d e " syn2 " : f æ r d i g " syn2 " e r gemt i syn2. ppm Laver b i l l e d e " syn3 " : f æ r d i g " syn3 " e r gemt i syn3. ppm Laver b i l l e d e " syn1 " : f æ r d i g " syn1 " e r gemt i syn1. ppm F.2 Afprøvning 2 Inddata <?xml version= 1. 0 encoding= utf 8?> <model> </ model> Forventet uddata En fejlmeddelelse om at roden skal være scene. 84

85 syn1.ppm syn2.ppm syn3.ppm Figur 1: Billeder fra afprøvning 1 Faktisk uddata I n d l æ s e r afproev_2. xml... Der e r en f e j l i afproev_2. xml: ( s c e n e ) Roden s k a l være s c e n e ( i k k e model ) Programmet a f s l u t t e s F.3 Afprøvning 3 Inddata <?xml version= 1. 0 encoding= utf 8?> <s c e n e> <p i l o t s y n hoejde=" 150 " bredde=" 150 "> <punkt i d=" p i l o t o e j e " x="0" y=" 2800" z=" 800 "/> <punkt i d=" cockpitvindue_ stedpunkt " x=" 207" y=" 2400" z=" 434 "/> <punkt i d=" cockpitvindue_ vandret " x=" 414 " y=" 0" z=" 0"/> <punkt i d=" c o c k p i t v i n d u e _ l o d r e t " x="0" y=" 141 " z=" 389 "/> </ p i l o t s y n> </ s c e n e> Forventet uddata En fejlmeddelelse om at id skal angives for pilotsyn. Faktisk uddata I n d l æ s e r afproev_3. xml... Der e r en f e j l i afproev_3. xml: ( s c e n e ) >( p i l o t s y n ) >i d 85

Afstande, skæringer og vinkler i rummet

Afstande, skæringer og vinkler i rummet Afstande, skæringer og vinkler i rummet Frank Nasser 9. april 20 c 2008-20. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her.

Læs mere

Afstande, skæringer og vinkler i rummet

Afstande, skæringer og vinkler i rummet Afstande, skæringer og vinkler i rummet Frank Villa 2. maj 202 c 2008-20. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Indhold

Læs mere

Michael Jokil 11-05-2012

Michael Jokil 11-05-2012 HTX, RTG Det skrå kast Informationsteknologi B Michael Jokil 11-05-2012 Indholdsfortegnelse Indledning... 3 Teori... 3 Kravspecifikationer... 4 Design... 4 Funktionalitet... 4 Brugerflade... 4 Implementering...

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2016 Projekt, del III Institut for matematik og datalogi Syddansk Universitet 20. april, 2016 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

Matlab script - placering af kran

Matlab script - placering af kran Matlab script - placering af kran 1 Til at beregne den ideelle placering af kranen hos MSK, er der gjort brug af et matlab script. Igennem dette kapitel vil opbygningen af dette script blive gennemgået.

Læs mere

Ting man gør med Vektorfunktioner

Ting man gør med Vektorfunktioner Ting man gør med Vektorfunktioner Frank Nasser. april 11 c 8-11. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Bemærk: Dette

Læs mere

Projekt 1.4 Tagrendeproblemet en instruktiv øvelse i modellering med IT.

Projekt 1.4 Tagrendeproblemet en instruktiv øvelse i modellering med IT. Projekt 1.4 Tagrendeproblemet en instruktiv øvelse i modellering med IT. Projektet kan bl.a. anvendes til et forløb, hvor en af målsætningerne er at lære om samspillet mellem værktøjsprogrammernes geometriske

Læs mere

Ting man gør med Vektorfunktioner

Ting man gør med Vektorfunktioner Ting man gør med Vektorfunktioner Frank Villa 3. august 13 Dette dokument er en del af MatBog.dk 8-1. IT Teaching Tools. ISBN-13: 978-87-9775--9. Se yderligere betingelser for brug her. Indhold 1 Introduktion

Læs mere

Pointen med Funktioner

Pointen med Funktioner Pointen med Funktioner Frank Nasser 0. april 0 c 0080. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Bemærk: Dette er en

Læs mere

Løsning af simple Ligninger

Løsning af simple Ligninger Løsning af simple Ligninger Frank Nasser 19. april 2011 c 2008-2011. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Bemærk:

Læs mere

Egenskaber ved Krydsproduktet

Egenskaber ved Krydsproduktet Egenskaber ved Krydsproduktet Frank Nasser 23. december 2011 2008-2011. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Indhold

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2017 Projekt, del III Institut for matematik og datalogi Syddansk Universitet 6. april, 2017 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

Martin Geisler. Uge 49, 2001

Martin Geisler. Uge 49, 2001 Min dintprog-browser Martin Geisler Uge 49, 2001 Resumé Dette dokument beskriver tankerne bag min dintprog-browser, en browser skrevet i Java der skal kunne fortolke en mindre delmængde af HTML 4, kaldet

Læs mere

Hvad er matematik? C, i-bog ISBN 978 87 7066 499 8

Hvad er matematik? C, i-bog ISBN 978 87 7066 499 8 Et af de helt store videnskabelige projekter i 1700-tallets Danmark var kortlægningen af Danmark. Projektet blev varetaget af Det Kongelige Danske Videnskabernes Selskab og løb over en periode på et halvt

Læs mere

Simulering af stokastiske fænomener med Excel

Simulering af stokastiske fænomener med Excel Simulering af stokastiske fænomener med Excel John Andersen, Læreruddannelsen i Aarhus, VIA Det kan være en ret krævende læreproces at udvikle fornemmelse for mange begreber fra sandsynlighedsregningen

Læs mere

Beskæring af et billede med Vegas Pro

Beskæring af et billede med Vegas Pro Beskæring af et billede med Vegas Pro Gary Rebholz Event Pan / Crop værktøj, som du finder på alle video begivenhed i dit projekt giver dig masser af power til at justere udseendet af din video. Du har

Læs mere

Skriftlig Eksamen Kombinatorik, sandsynlighed og randomiserede algoritmer (DM528)

Skriftlig Eksamen Kombinatorik, sandsynlighed og randomiserede algoritmer (DM528) Skriftlig Eksamen Kombinatorik, sandsynlighed og randomiserede algoritmer (DM58) Institut for Matematik & Datalogi Syddansk Universitet Torsdag den 7 Januar 010, kl. 9 13 Alle sædvanlige hjælpemidler (lærebøger,

Læs mere

VisiRegn: En e-bro mellem regning og algebra

VisiRegn: En e-bro mellem regning og algebra Artikel i Matematik nr. 2 marts 2001 VisiRegn: En e-bro mellem regning og algebra Inge B. Larsen Siden midten af 80 erne har vi i INFA-projektet arbejdet med at udvikle regne(arks)programmer til skolens

Læs mere

cvbnmrtyuiopasdfghjklæøzxcvbnmq wertyuiopåasdfghjklæøzxcvbnmqw ertyuiopåasdfghjklæøzxcvbnmqwer tyuiopåasdfghjklæøzxcvbnmqwerty

cvbnmrtyuiopasdfghjklæøzxcvbnmq wertyuiopåasdfghjklæøzxcvbnmqw ertyuiopåasdfghjklæøzxcvbnmqwer tyuiopåasdfghjklæøzxcvbnmqwerty cvbnmrtyuiopasdfghjklæøzxcvbnmq wertyuiopåasdfghjklæøzxcvbnmqw ertyuiopåasdfghjklæøzxcvbnmqwer tyuiopåasdfghjklæøzxcvbnmqwerty Matematik Den kinesiske prøve uiopåasdfghjklæøzxcvbnmqwertyui 45 min 01 11

Læs mere

Vinkelrette linjer. Frank Villa. 4. november 2014

Vinkelrette linjer. Frank Villa. 4. november 2014 Vinkelrette linjer Frank Villa 4. november 2014 Dette dokument er en del af MatBog.dk 2008-2012. IT Teaching Tools. ISBN-13: 978-87-92775-00-9. Se yderligere betingelser for brug her. Indhold 1 Introduktion

Læs mere

Målet for disse slides er at diskutere nogle metoder til at gemme og hente data effektivt.

Målet for disse slides er at diskutere nogle metoder til at gemme og hente data effektivt. Merging og hashing Mål Målet for disse slides er at diskutere nogle metoder til at gemme og hente data effektivt. Dette emne er et uddrag af kurset DM507 Algoritmer og datastrukturer (2. semester). Mål

Læs mere

Progression frem mod skriftlig eksamen

Progression frem mod skriftlig eksamen Progression frem mod skriftlig eksamen Ikke alle skal have 12 Eksamensopgavernes funktion i det daglige og til eksamen Progression i sættet progression i den enkelte opgave Hvornår inddrages eksamensopgaver

Læs mere

It og informationssøgning Forelæsning december 2006 Nils Andersen. Indkøring, afprøvning og dokumentation af programmer

It og informationssøgning Forelæsning december 2006 Nils Andersen. Indkøring, afprøvning og dokumentation af programmer It og informationssøgning Forelæsning 14 13. december 2006 Nils Andersen Indkøring, afprøvning og dokumentation af programmer Indkøring Syntaksfejl Køretidsfejl Semantiske fejl Dokumentation Sammenfatning

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2019 Projekt, del III Institut for matematik og datalogi Syddansk Universitet 10. april, 2019 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

Hvis man ønsker mere udfordring, kan man springe de første 10 opgaver over. , og et punkt er givet ved: P (2, 1).

Hvis man ønsker mere udfordring, kan man springe de første 10 opgaver over. , og et punkt er givet ved: P (2, 1). Plangeometri Hvis man ønsker mere udfordring, kan man springe de første 10 opgaver over Opgave 1 To linjer er givet ved ligningerne: x y 0 og x b y 4 0, hvor b er en konstant a) Beregn konstanten b således,

Læs mere

Daglig brug af JitBesked 2.0

Daglig brug af JitBesked 2.0 Daglig brug af JitBesked 2.0 Indholdsfortegnelse Oprettelse af personer (modtagere)...3 Afsendelse af besked...4 Valg af flere modtagere...5 Valg af flere personer der ligger i rækkefølge...5 Valg af flere

Læs mere

Analytisk Geometri. Frank Nasser. 12. april 2011

Analytisk Geometri. Frank Nasser. 12. april 2011 Analytisk Geometri Frank Nasser 12. april 2011 c 2008-2011. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Bemærk: Dette er

Læs mere

π er irrationel Frank Nasser 10. december 2011

π er irrationel Frank Nasser 10. december 2011 π er irrationel Frank Nasser 10. december 2011 2008-2011. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Indhold 1 Introduktion

Læs mere

Geometrisk skæring. Afgørelse af om der findes skæringer blandt geometriske objekter Bestemmelse af alle skæringspunkter

Geometrisk skæring. Afgørelse af om der findes skæringer blandt geometriske objekter Bestemmelse af alle skæringspunkter Planfejning 1 Skæring 2 Geometrisk skæring Afgørelse af om der findes skæringer blandt geometriske objekter Bestemmelse af alle skæringspunkter Løsningsmetoder: Rå kraft Planfejning (eng. plane sweep)

Læs mere

Aalborg Universitet - Adgangskursus. Eksamensopgaver. Matematik B til A

Aalborg Universitet - Adgangskursus. Eksamensopgaver. Matematik B til A Aalborg Universitet - Adgangskursus Eksamensopgaver Matematik B til A Undervisningsministeriet Universitetsafdelingen ADGANGSEKSAMEN Til ingeniøruddannelserne Matematik A xxdag den y.juni 00z kl. 9.00

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2013 Projekt, del I Institut for matematik og datalogi Syddansk Universitet 5. marts, 2013 Dette projekt udleveres i to dele. Hver del har sin deadline, således

Læs mere

I kapitlet arbejdes med følgende centrale matematiske objekter og begreber:

I kapitlet arbejdes med følgende centrale matematiske objekter og begreber: INTRO Efter mange års pause er trigonometri med Fælles Mål 2009 tilbage som fagligt emne i grundskolens matematikundervisning. Som det fremgår af den følgende sides udpluk fra faghæftets trinmål, er en

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2016 Projekt, del I Institut for matematik og datalogi Syddansk Universitet 29. februar, 2016 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

Lærervejledning Matematik 1-2-3 på Smartboard

Lærervejledning Matematik 1-2-3 på Smartboard Lærervejledning Matematik 1-2-3 på Smartboard Lærervejledning til Matematik 1-2-3 på Smartboard Materialet består af 33 færdige undervisningsforløb til brug i matematikundervisningen i overbygningen. Undervisningsforløbene

Læs mere

Emneopgave: Lineær- og kvadratisk programmering:

Emneopgave: Lineær- og kvadratisk programmering: Emneopgave: Lineær- og kvadratisk programmering: LINEÆR PROGRAMMERING I lineær programmering løser man problemer hvor man for en bestemt funktion ønsker at finde enten en maksimering eller en minimering

Læs mere

5. OPSÆTNING DOKUMENTSKABELONER 5.1 TRIN

5. OPSÆTNING DOKUMENTSKABELONER 5.1 TRIN 5. OPSÆTNING DOKUMENTSKABELONER Under fanen Dok. skabeloner kan du arbejde med de skabeloner som du har i systemet, eller du kan oprette nye. I denne vejledning kigger vi på hvordan du kan tilrette selve

Læs mere

Geogebra Begynder Ku rsus

Geogebra Begynder Ku rsus Navn: Klasse: Matematik Opgave Kompendium Geogebra Begynder Ku rsus Kompendiet indeholder: Mål side længder Mål areal Mål vinkler Vinkelhalveringslinje Indskrevne cirkel Midt normal Omskrevne cirkel Trekant

Læs mere

Kommentarer til den ægyptiske beregning Kommentarer til den ægyptiske beregning... 5

Kommentarer til den ægyptiske beregning Kommentarer til den ægyptiske beregning... 5 Hvad er matematik? C, i-bog ISBN 978 87 7066 499 8 Projekter: Kapitel - Projektet er delt i to små projekter, der kan laves uafhængigt af hinanden. Der afsættes fx - timer til vejledning med efterfølgende

Læs mere

Fagårsplan 10/11 Fag: Matematik Klasse: 7.ABC Lærer: Henrik Stillits. Fagområde/ emne

Fagårsplan 10/11 Fag: Matematik Klasse: 7.ABC Lærer: Henrik Stillits. Fagområde/ emne Fagårsplan 10/11 Fag: Matematik Klasse: 7.ABC Lærer: Henrik Stillits. Fagområde/ emne Matematiske færdigheder Grundlæggende færdigheder - plus, minus, gange, division (hele tal, decimaltal og brøker) Identificer

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2018 Projekt, del II Institut for matematik og datalogi Syddansk Universitet 13. marts, 2018 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

a. Find ud af mere om sprogteknologi på internettet. Hvad er nogle typiske anvendelser? Hvor mange af dem bruger du i din hverdag?

a. Find ud af mere om sprogteknologi på internettet. Hvad er nogle typiske anvendelser? Hvor mange af dem bruger du i din hverdag? En computer forstår umiddelbart ikke de sprog vi mennesker taler og skriver. Inden for sprogteknologien (på engelsk: Natural Language Processing eller NLP), der er en gren af kunstig intelligens, beskæftiger

Læs mere

Retningslinjer for bedømmelsen. Georg Mohr-Konkurrencen 2010 2. runde

Retningslinjer for bedømmelsen. Georg Mohr-Konkurrencen 2010 2. runde Retningslinjer for bedømmelsen. Georg Mohr-Konkurrencen 2010 2. runde Det som skal vurderes i bedømmelsen af en besvarelse, er om deltageren har formået at analysere problemstillingen, kombinere de givne

Læs mere

Projekt 3.7. Pythagoras sætning

Projekt 3.7. Pythagoras sætning Projekt 3.7. Pythagoras sætning Flere beviser for Pythagoras sætning... Bevis for Pythagoras sætning ved anvendelse af ensvinklede trekanter... Opgave 1: Et kinesisk og et indisk bevis for Pythagoras sætning...

Læs mere

Projekt 3.1 Pyramidestub og cirkelareal

Projekt 3.1 Pyramidestub og cirkelareal Projekt. Pyramidestub og cirkelareal - i tilknytning til afsnit., især for A Indhold Rumfanget af en pyramidestub... Moderne metode... Ægyptisk metode... Kommentarer til den ægyptiske beregning... Arealet

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2018 Projekt, del II Institut for matematik og datalogi Syddansk Universitet 20. marts, 2019 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

Kom godt i gang med Fable-robotten

Kom godt i gang med Fable-robotten Kom godt i gang med Fable-robotten 1. Først skal du installere programmet på din computer. Gå ind på shaperobotics.com og under support vælger du download: Her vælger du, under PC App om du kører Windows

Læs mere

Fable Kom godt i gang

Fable Kom godt i gang Fable Kom godt i gang Opdateret: 26-03-2018 Indholdsfortegnelse 1. Først skal du installere programmet på din computer 3 2. Når programmet er installeret er du klar til at pakke robotten ud 4 3. Nu er

Læs mere

Design af IT-medier. Skriftlig prøve 27. august 1999. Alle skriftlige hjælpemidler er tilladt.

Design af IT-medier. Skriftlig prøve 27. august 1999. Alle skriftlige hjælpemidler er tilladt. Design af IT-medier Skriftlig prøve 27. august 1999 Varighed: Hjælpemidler: Bedømmelse: Besvarelse: Opgaver: 4 timer. Alle skriftlige hjælpemidler er tilladt. Karakter efter 13-skalaen. Alle ark skal være

Læs mere

Skriftlig eksamen i Datalogi

Skriftlig eksamen i Datalogi Roskilde Universitetscenter side 1 af 9 sider Skriftlig eksamen i Datalogi Modul 1 Vinter 1999/2000 Opgavesættet består af 6 opgaver, der ved bedømmelsen tillægges følgende vægte: Opgave 1 5% Opgave 2

Læs mere

Hvis man ønsker mere udfordring, kan man springe de første 10 opgaver over. 1, og et punkt er givet ved: (2, 1)

Hvis man ønsker mere udfordring, kan man springe de første 10 opgaver over. 1, og et punkt er givet ved: (2, 1) Plangeometri Hvis man ønsker mere udfordring, kan man springe de første 10 opgaver over. Opgave 1 To linjer er givet ved ligningerne: x y 0 og x b y 4 0, hvor b er en konstant. a) Beregn konstanten b således,

Læs mere

Noter til Perspektiver i Matematikken

Noter til Perspektiver i Matematikken Noter til Perspektiver i Matematikken Henrik Stetkær 25. august 2003 1 Indledning I dette kursus (Perspektiver i Matematikken) skal vi studere de hele tal og deres egenskaber. Vi lader Z betegne mængden

Læs mere

Formativ brug af folkeskolens prøver årets resultater på landsplan Den skriftlige prøve i matematik med hjælpemidler, FP9 maj 2019

Formativ brug af folkeskolens prøver årets resultater på landsplan Den skriftlige prøve i matematik med hjælpemidler, FP9 maj 2019 Formativ brug af folkeskolens prøver årets resultater på landsplan Den skriftlige prøve i matematik med hjælpemidler, FP9 maj 2019 Skrevet af Klaus Fink på baggrund af oplysninger fra opgavekommissionen

Læs mere

Simulering af stokastiske fænomener med Excel

Simulering af stokastiske fænomener med Excel Simulering af stokastiske fænomener med Excel John Andersen, Læreruddannelsen i Aarhus, VIA Det kan være en ret krævende læreproces at udvikle fornemmelse for mange begreber fra sandsynlighedsregningen

Læs mere

Analytisk plangeometri 1

Analytisk plangeometri 1 1 Analytisk plangeometri 1 Kære 1. x, Vi begynder dag vores forløb om analytisk plangeometri. Dette bliver en udvidelse af ting i allerede kender til, så noget ved I i forvejen, mens andet bliver helt

Læs mere

Matematik for lærerstuderende klasse Geometri

Matematik for lærerstuderende klasse Geometri Matematik for lærerstuderende 4.-10. klasse Geometri Klassisk geometri (kapitel 6) Deduktiv tankegang Ræsonnementskompetence Mål med kapitlet: Erkender Thales sætning som fundament for afstandsberegning.

Læs mere

Grådige algoritmer. Et generelt algoritme-konstruktionsprincip ( paradigme ) for optimeringsproblemer.

Grådige algoritmer. Et generelt algoritme-konstruktionsprincip ( paradigme ) for optimeringsproblemer. Grådige algoritmer Grådige algoritmer Et generelt algoritme-konstruktionsprincip ( paradigme ) for optimeringsproblemer. Grådige algoritmer Et generelt algoritme-konstruktionsprincip ( paradigme ) for

Læs mere

Matematik. Matematiske kompetencer

Matematik. Matematiske kompetencer Matematiske kompetencer skelne mellem definitioner og sætninger, mellem enkelttilfælde og generaliseringer og anvende denne indsigt til at udforske og indgå i dialog om forskellige matematiske begrebers

Læs mere

VEKTORGEOMETRI del 2 Skæringer Projektioner Vinkler Afstande

VEKTORGEOMETRI del 2 Skæringer Projektioner Vinkler Afstande VEKTORGEOMETRI del Skæringer Projektioner Vinkler Afstande x-klasserne Gammel Hellerup Gymnasium Februar 019 ; Michael Szymanski ; mz@ghg.dk 1 Indhold OVERSIGT... 3 SKÆRINGSPUNKTER OG RØRINGSPUNKTER...

Læs mere

ANALOG vs DIGITAL. figur 1: fotografi af en blyantsstreg. figur 2: en linje beskrevet som formel er omsat til pixels

ANALOG vs DIGITAL. figur 1: fotografi af en blyantsstreg. figur 2: en linje beskrevet som formel er omsat til pixels ANALOG vs DIGITAL Ordet digitalt bliver brugt ofte indenfor skitsering. Definitionen af digitalt er en elektronisk teknologi der genererer, gemmer, og processerer data ved at benytte to tilstande: positiv

Læs mere

Danmarks Tekniske Universitet

Danmarks Tekniske Universitet side af sider Danmarks Tekniske Universitet Skriftlig prøve, den. maj 00. Kursusnavn Algoritmer og datastrukturer I Kursus nr. 005. Tilladte hjælpemidler: Alle skriftlige hjælpemidler. Vægtning af opgaverne:

Læs mere

Polynomiumsbrøker og asymptoter

Polynomiumsbrøker og asymptoter Polynomiumsbrøker og asymptoter Frank Villa 9. marts 2012 c 2008-2011. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Indhold

Læs mere

Hvad er formel logik?

Hvad er formel logik? Kapitel 1 Hvad er formel logik? Hvad er logik? I daglig tale betyder logisk tænkning den rationelt overbevisende tænkning. Og logik kan tilsvarende defineres som den rationelle tænknings videnskab. Betragt

Læs mere

Projekt 6.7. Beviser for Pythagoras sætning - og konstruktion af animationer

Projekt 6.7. Beviser for Pythagoras sætning - og konstruktion af animationer Projekt 6.7. Beviser for Pythagoras sætning - og konstruktion af animationer Flere beviser for Pythagoras sætning 1 Bevis for Pythagoras sætning ved anvendelse af ensvinklede trekanter... 1 Opgave 1 Et

Læs mere

Formativ brug af folkeskolens prøver. Den skriftlige prøve i matematik med hjælpemidler, FP9 maj 2018

Formativ brug af folkeskolens prøver. Den skriftlige prøve i matematik med hjælpemidler, FP9 maj 2018 Formativ brug af folkeskolens prøver Den skriftlige prøve i matematik med hjælpemidler, FP9 maj 2018 1 Til matematiklæreren i 9. klasse Dette er en rapport om den skriftlige prøve i matematik med hjælpemidler

Læs mere

Danmarks Tekniske Universitet

Danmarks Tekniske Universitet side af sider Danmarks Tekniske Universitet Skriftlig prøve, den 6. maj 0. Kursusnavn: Algoritmer og datastrukturer I Kursus nr. 005. Tilladte hjælpemidler: Skriftlige hjælpemidler. Varighed: timer Vægtning

Læs mere

3. Om skalamønstrene og den indfoldede orden

3. Om skalamønstrene og den indfoldede orden Dette er den tredje af fem artikler under den fælles overskrift Studier på grundlag af programmet SKALAGENERATOREN (forfatter: Jørgen Erichsen) 3. Om skalamønstrene og den indfoldede orden Lad os begynde

Læs mere

MODELSÆT 2; MATEMATIK TIL LÆREREKSAMEN

MODELSÆT 2; MATEMATIK TIL LÆREREKSAMEN MODELSÆT ; MATEMATIK TIL LÆREREKSAMEN Forberedende materiale Den individuelle skriftlige røve i matematik vil tage udgangsunkt i følgende materiale:. En diskette med to regnearks-filer og en MathCad-fil..

Læs mere

Euklids algoritme og kædebrøker

Euklids algoritme og kædebrøker Euklids algoritme og kædebrøker Michael Knudsen I denne note vil vi med Z, Q og R betegne mængden af henholdsvis de hele, de rationale og de reelle tal. Altså er { m } Z = {..., 2,, 0,, 2,...} og Q = n

Læs mere

Skriftlig Eksamen DM507 Algoritmer og Datastrukturer

Skriftlig Eksamen DM507 Algoritmer og Datastrukturer Skriftlig Eksamen DM507 Algoritmer og Datastrukturer Institut for Matematik og Datalogi Syddansk Universitet, Odense Tirsdag den 24. juni 2014, kl. 10:00 14:00 Besvarelsen skal afleveres elektronisk. Se

Læs mere

Mere om differentiabilitet

Mere om differentiabilitet Mere om differentiabilitet En uddybning af side 57 i Spor - Komplekse tal Kompleks funktionsteori er et af de vigtigste emner i matematikken og samtidig et af de smukkeste I bogen har vi primært beskæftiget

Læs mere

Fraktaler. Mandelbrots Mængde. Foredragsnoter. Af Jonas Lindstrøm Jensen. Institut For Matematiske Fag Århus Universitet

Fraktaler. Mandelbrots Mængde. Foredragsnoter. Af Jonas Lindstrøm Jensen. Institut For Matematiske Fag Århus Universitet Fraktaler Mandelbrots Mængde Foredragsnoter Af Jonas Lindstrøm Jensen Institut For Matematiske Fag Århus Universitet Indhold Indhold 1 1 Komplekse tal 3 1.1 Definition.......................................

Læs mere

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer DM507 Algoritmer og datastrukturer Forår 2019 Projekt, del I Institut for matematik og datalogi Syddansk Universitet 27. februar, 2019 Dette projekt udleveres i tre dele. Hver del har sin deadline, således

Læs mere

Gruppeteori. Michael Knudsen. 8. marts For at motivere indførelsen af gruppebegrebet begynder vi med et eksempel.

Gruppeteori. Michael Knudsen. 8. marts For at motivere indførelsen af gruppebegrebet begynder vi med et eksempel. Gruppeteori Michael Knudsen 8. marts 2005 1 Motivation For at motivere indførelsen af gruppebegrebet begynder vi med et eksempel. Eksempel 1.1. Lad Z betegne mængden af de hele tal, Z = {..., 2, 1, 0,

Læs mere

EA3 eller EA Cube rammeværktøjet fremstilles visuelt som en 3-dimensionel terning:

EA3 eller EA Cube rammeværktøjet fremstilles visuelt som en 3-dimensionel terning: Introduktion til EA3 Mit navn er Marc de Oliveira. Jeg er systemanalytiker og datalog fra Københavns Universitet og denne artikel hører til min artikelserie, Forsimpling (som også er et podcast), hvor

Læs mere

Computerundervisning

Computerundervisning Frederiksberg Seminarium Computerundervisning Koordinatsystemer og Funktioner Lærervejledning 12-02-2009 Udarbejdet af: Pernille Suhr Poulsen Christina Klitlyng Julie Nielsen Indhold Introduktion... 3

Læs mere

Introduktion til den afledede funktion

Introduktion til den afledede funktion Introduktion til den afledede funktion Scenarie: Rutsjebanen Tilsigtede viden Bredere kompetencemål Nødvendige matematiske forudsætninger Tid Niveau Materialer til rådighed At give en forståelse for konceptet

Læs mere

Ide med Diff. Mål. Tidsplan. 1.uge: 2.uge:

Ide med Diff. Mål. Tidsplan. 1.uge: 2.uge: Side 1 af 5 Ide med Diff. Min ide med differenertierings modulet er at lave et program som kan vise 3d objekter, og få lavede en konverter som kan konventer 3ds filer over til noget som flash kan bruge.

Læs mere

Årsplan for 7. klasse, matematik

Årsplan for 7. klasse, matematik Årsplan for 7. klasse, matematik I matematik bruger vi bogsystemet Sigma som grundmateriale. I systemet er der, ud over grundbogen, også kopiark og tests tilknyttet de enkelte kapitler. Systemet er udarbejdet

Læs mere

Fable Kom godt i gang

Fable Kom godt i gang Fable Kom godt i gang Vers. 1.3.1 Opdateret: 29-08-2018 Indholdsfortegnelse 1. Installer programmet 3 2. Pak robotten ud 5 3. I gang med at programmere 6 4. Programmér Fable til at køre fra 90 til -90

Læs mere

Delmængder af Rummet

Delmængder af Rummet Delmængder af Rummet Frank Villa 15. maj 2012 c 2008-2011. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Indhold 1 Introduktion

Læs mere

Bliv opdaget på Internettet! - 10 gode råd til at optimere din hjemmeside til søgemaskiner

Bliv opdaget på Internettet! - 10 gode råd til at optimere din hjemmeside til søgemaskiner Bliv opdaget på Internettet! - 10 gode råd til at optimere din hjemmeside til søgemaskiner Af Henrik Bro og Martin T. Hansen I har måske allerede en flot, og informativ hjemmeside. Og alle jeres kursister

Læs mere

Geometri i plan og rum

Geometri i plan og rum INTRO I kapitlet arbejder eleverne med plane og rumlige figurers egenskaber og med deres anvendelse som geometriske modeller. I den forbindelse kommer de bl.a. til at beskæftige sig med beregninger af

Læs mere

Trigonometri. Store konstruktioner. Måling af højde

Trigonometri. Store konstruktioner. Måling af højde Trigonometri Ordet trigonometri er sammensat af de to ord trigon og metri, hvor trigon betyder trekant og metri kommer af det græske ord metros, som kan oversættes til måling. Så ordet trigonometri er

Læs mere

Projekt - Visual Basic for Applications N på stribe

Projekt - Visual Basic for Applications N på stribe Projekt - Visual Basic for Applications N på stribe Mikkel Kaas og Troels Henriksen - 03x 3. november 2005 1 Introduktion Spillet tager udgangspunkt i det gamle kendte 4 på stribe, dog med den ændring,

Læs mere

Design af IT-medier. Skriftlig prøve 10. juni Alle skriftlige hjælpemidler er tilladt.

Design af IT-medier. Skriftlig prøve 10. juni Alle skriftlige hjælpemidler er tilladt. Design af IT-medier Skriftlig prøve 10. juni 1999 Varighed: Hjælpemidler: Bedømmelse: Besvarelse: Opgaver: 4 timer. Alle skriftlige hjælpemidler er tilladt. Karakter efter 13-skalaen. Alle ark skal være

Læs mere

Vektorer og lineær regression

Vektorer og lineær regression Vektorer og lineær regression Peter Harremoës Niels Brock April 03 Planproduktet Vi har set, at man kan gange en vektor med et tal Et oplagt spørgsmål er, om man også kan gange to vektorer med hinanden

Læs mere

Skolens formål med faget matematik følger beskrivelsen af formål i folkeskolens Fælles Mål:

Skolens formål med faget matematik følger beskrivelsen af formål i folkeskolens Fælles Mål: Formål: Skolens formål med faget matematik følger beskrivelsen af formål i folkeskolens Fælles Mål: Formålet med undervisningen i matematik er, at eleverne bliver i forstå og anvende matematik i sammenhænge,

Læs mere

Sådan kommer du i gang med GeomeTricks

Sådan kommer du i gang med GeomeTricks Sådan kommer du i gang med GeomeTricks Ved hjælp af programmet GeomeTricks kan du tegne figurer i geometri. Når du tegner en figur, så skal du opbygge din figur ved hjælp af geometriske objekter. Geometriske

Læs mere

Identifikation af planer der ikke findes i PlansystemDK vha. datasættet... 9

Identifikation af planer der ikke findes i PlansystemDK vha. datasættet... 9 Vejledning i brug af Tingbogsudtrækket Version 1.0 af 1. juli 2009 Indhold Indledning... 1 Planer i Tingbogen... 2 Planer i PlansystemDK... 3 Sammenhæng mellem Tingbogen og PlansystemDK... 3 Datastruktur...

Læs mere

Egenskaber ved Krydsproduktet

Egenskaber ved Krydsproduktet Egenskaber ved Krydsproduktet Frank Nasser 12. april 2011 c 2008-2011. Dette dokument må kun anvendes til undervisning i klasser som abonnerer på MatBog.dk. Se yderligere betingelser for brug her. Bemærk:

Læs mere

Papirfoldning. en matematisk undersøgelse til brug i din undervisning.

Papirfoldning. en matematisk undersøgelse til brug i din undervisning. Papirfoldning en matematisk undersøgelse til brug i din undervisning. Når man folder og klipper figurer kan man blive irriteret over at skulle vende og dreje saksen. Hvor få klip kan man mon nøjes med?

Læs mere

Eleverne skal lære at:

Eleverne skal lære at: PK: Årsplan 8.Ga. M, matematik Tid og fagligt område Aktivitet Læringsmål Uge 32 uge 50 Tal og algebra Eleverne skal arbejde med at: kende de reelle tal og anvende dem i praktiske og teoretiske sammenhænge

Læs mere

Udskæring med Vegas Pro multi-kamera redigeringsværktøjer

Udskæring med Vegas Pro multi-kamera redigeringsværktøjer Udskæring med Vegas Pro multi-kamera redigeringsværktøjer Gary Rebholz Med høj kvalitet kameraer bliver mere og mere overkommelig et stigende antal redaktører står nu over for at skære sammen flere optagelser,

Læs mere

Brugergrænseflader i VSU

Brugergrænseflader i VSU 28-10-09 Side 1/5 Brugergrænseflader i Dette notat giver et praktisk eksempel på, hvordan brugergrænsefladen kan håndteres i. Notatet er en konsekvens af en lidt overfladisk beskrivelse i [B&D00] samt

Læs mere

Fraktaler Mandelbrots Mængde

Fraktaler Mandelbrots Mængde Fraktaler Mandelbrots Mængde Foredragsnoter Af Jonas Lindstrøm Jensen Institut For Matematiske Fag Århus Universitet Indhold Indhold 1 1 Indledning 3 2 Komplekse tal 5 2.1 Definition.......................................

Læs mere

Formativ brug af folkeskolens prøver årets resultater på landsplan Den skriftlige prøve i matematik FP10 maj 2019

Formativ brug af folkeskolens prøver årets resultater på landsplan Den skriftlige prøve i matematik FP10 maj 2019 Formativ brug af folkeskolens prøver årets resultater på landsplan Den skriftlige prøve i matematik FP10 maj 2019 Skrevet af Klaus Fink på baggrund af oplysninger fra opgavekommissionen 1 Til matematiklæreren

Læs mere

Anvendelse af matematik til konkrete beregninger

Anvendelse af matematik til konkrete beregninger Anvendelse af matematik til konkrete beregninger ved J.B. Sand, Datalogisk Institut, KU Praktisk/teoretisk PROBLEM BEREGNINGSPROBLEM og INDDATA LØSNINGSMETODE EVT. LØSNING REGNEMASKINE Når man vil regne

Læs mere

Visualiseringsprogram

Visualiseringsprogram Visualiseringsprogram Programmering C - eksamensopgave Rami Kaddoura og Martin Schmidt Klasse: 3.4 Vejleder: Karl Bjarnason Roskilde Tekniske Gymnasium Udleveringsdato: 02-03-2012 Afleveringsdato: 11-05-12

Læs mere

Lineære ligningssystemer

Lineære ligningssystemer enote 2 1 enote 2 Lineære ligningssystemer Denne enote handler om lineære ligningssystemer, om metoder til at beskrive dem og løse dem, og om hvordan man kan få overblik over løsningsmængdernes struktur.

Læs mere