Ytflykten.

Till startsidan Föregående sida Innehåll

Den här sidan är ett exempel på hur man visar ett flygplan i valfri rotation, storlek och orientering på en koordinatyta med hjälp av operationer på ett antal vektorer. På sidan används Pseudokod för att beskriva dom algoritmer och operationer som krävs för att göra jobbet.

(Jag har inte på långt när skrivit färdigt den delen men när det är någorlunda klart så är det tänkt att nyckelorden jag använder i min pseudokod skall vara upplänkade till sidor där dom är utförligt förklarade så att man bara behöver klicka på ordet man inte förstår hur det används och läsa förklaringen för det.)

Ritning :

Flygplanet har konstruerats med hjälp av åtta punkter : 1 - 8 som sedan bundits samman med linjer i en sekvens av 10 vektorer. Sekvensen startar i spetsen av noskonen och går sedan : 1 - 2 - 3 - 4 - 5 - 2 - 8 - 7 - 6 - 4 - 1. Det är även möjligt att rita planet genom att dra upp 8 separata vektorer i lnjerna : 1 - 2, 1 - 4, 3 - 8, 3 - 6, 5 - 2, 5 - 4 men jag har valt att göra så här för att det skall vara möjligt att translera från punkt till punkt utan att avbryta serien. Flygplanet har även medvetet definerats så att nosen pekar i vinkel 0° så att det inte behöver roteras om vi vill förflytta oss framåt längst med den positiva x-axeln. Samtliga punkter ligger inom enhetscirkeln där punkten 1 (nosen) har den störsa radien : [1.0, 0.0].

För att skapa en vektoranimation så bör man alltså först definera det eller dom objekt som skall visas. Det görs vanligtvis i en editor som är avsedd för att skapa vektorobjekt (vid enkla figurer som denna kan man skriva in koordinterna direkt i programmet). Sedan överförs objektet till animationsprogrammet på något sätt, till exempel genom att läsa in koordinaterna från den fil som man sparade objektet i.

Jag har valt att definera två indexerade flyttalsvariabler : objekt_x [antal punkter] och objekt_y [antal punkter] och sedan läsa in koordinaterna dit :

: Först defineras nödvändiga konstanter och variabler :
Konstant antal_punkter = 8 - 1   : Antal koordinater i objektet. (Kommentar) :
Skapa Heltal index               : Variabel för indexräknaren :
Flyttal objekt_x [antal_punkter] : Skapa Variabel för objektets x koorinater :
Flyttal objekt_y [antal_punkter] : Skapa variabel för objektets y koorinater :
: Sedan initieras vektorerna med lämpliga värden som till exempel -
: kan hämtas från en öppen fil eller en funktion som skapar beloppen :
Räkna index från 0 till antal_punkter
  Sätt objekt_x [index] Till Hämta_värde [x koordinattabell]
  Sätt objekt_y [index] Till Hämta_värde [y koordinattabell]
Nästa index 
: Därefter skapas en referenstabell som anger i vilken-
: ordning punkterna skall bindas samman till en polygon :
Konstant antal_vektorer = 10 - 1  : Antal vektorer i polygonen. :
Heltal ploygon [antal_vektorer]   : Skapa Variabel för polygonen. :
: Sedan initieras polgonen med värden som motsvarar den ordning man önskar :
Räkna index från 0 till antal_vektorer
  Sätt Polygon [index] Till Hämta_värde [koordinatordningstabell]
Nästa index
****
Visa :

För att visa ytflyktsplanet så krävs det det en bildyta. Grafen till vänster motsvarar bidlskärmen indelad i ett koordinatsystem på ±10 rutor där origo [0.0, 0.0] som sig bör ligger mitt i bilden och det nedre vänstra hörnet motsvarar koordinaten [-1.0, -1.0] och sedan medurs nedre högra [1.0, -1.0], övre högra [1.0, 1.0] samt [-1.0, 1.0] uppe till vänster. Varje ruta har storleken [0.1, 0.1] enheter och hela ytan [2.0, 2.0] enheter.

****

Om vi nu vill vill skriva dit flygplanet så räcker det med att utgå från den första punkten i listan och sedan translera till nästa punkt i ordningen och sedan dra en linje från den förra punkten till den nya :

: Flygplanet skrivs dit linje för linje, vi börjar i punkt ett (1) och drar en linje 
: dit från den förra, punkt noll (0) och stegar oss sedan vidare till nästa punkt :
Räkna index Från 1 Till antal_vektorer
  Visa_linje Från
    objekt_x [ploygon [index - 1]], objekt_y [ploygon [index - 1]]
  Till
    objekt_x [ploygon [index]], objekt_y [ploygon [index]]
Nästa index

Vilket medför att ytflyktsplanet visas mitt på ytan, planets nollpunkt i origo :

.

****

Placera :

Om nu ytflyktsplanet verkligen skall kunna flyga över ytan och inte bara visas mitt på så måste vi kunna anger var och hur. Därför skapas två vektorer. Den ena (vit) anger var planet befinner sig och den andra visar vart planet är på väg (gul).

Nu räcker det inte bara med att translera till den första punkten, dels är flygplanet lika stort som hela ytan och dessutom så pekar nosen alltid mot höger. Vad som krävs är skalning och rotation.

Vi väljer en skala på 1:3; s = 1.0 / 3.0 och för att få den rätta rotationsvinkeln så drar vi först den vita vektorn ifrån den gula; rosa = gul - vit. Sedan beräknas normalen för den nya vektorn. Normalvektorn kommer sedan att multipliceras med punkterna som bygger upp flygplanet och vi når på så sätt rätt vinkel.

****

Först skapas en temporär koordinattabell, det för att det skall vara lätt att göra operationer på objektet utan att för den saken skull behöva förstöra masterkopian med en massa rotation och skalning. Vi skapar även variabler för dom tre vektorerna och initierar den vita och den gula, den rosa beräknas sedan från dessa :

: Först den temporära Variabeln för objektets koordinater :
Skapa Flyttal tx [antal_punkter] : Temporär x-koordinattabell :
Skapa Flyttal ty [antal_punkter] : Temporär y-koordinattabell :
: Sedan vektorerna som initieras till punkterna dom pekar på i bilden :
Skapa Flyttal vit_x =  0.4
Skapa Flyttal vit_y =  0.3
Skapa Flyttal gul_x = -0.6
Skapa Flyttal gul_y =  0.8
: Och ytterligare en variabel som vi sparar normalvektorn i efter beräkning :
Skapa Flyttal o
Skapa Flyttal p
: Och en flyttalskonstant för skalningen :
Sakapa Konstant s = 1.0 / 3.0
: Dessutom så behöver vi en temporär reell variabel som används under beräkningarna,
  det för att vi inte kan göra operationer på både x och y samtidigt. Vi behöver
  någonstans att tillfälligt spara resultatet av beräkningen av x-koordinaten så
  att vi kan använda det gamla värdet även när vi beräknar den nya y-koordinaten :
Skapa Flyttal t
: Nu har vi allt vi behöver :-) Först beräknas normalen :
Sätt o Till gul_x - vit_x
Sätt p Till gul_y - vit_y
Sätt t Till Roten_ur [o · o + p · p]
Sätt o Till o / t
Sätt p Till p / t

Nu är det viktigt (och det här gäller även när man skapar fraktaler) att vi roterar och skalar innan vi utför translationen för annars så kommer vi att utföra dom operationerna även på den vita positionsvektorn. Det som sker vid translation är att man lägger till (adderar) en vektor till samtliga vektorer i objektet. Translerar vi innan rotation och skalning (där har ordningen däremot ingen betydelse) så kommer vi att hama i rätt vinkel men på fel plats, den plats den transformerade vita vektorn kommer att peka på och det vill vi ju inte. Nosen kommer heller inte att peka mot målvektorn (gul) utan i den vinkeln som anges av normalvektorn (rosa pil) som ju är rätt vinkel om vi bara tar oss till rätt plats.

Nu gör vi det här stilfullt och skriver ihop hela operationen till en enda formel : z' = z · q · s + p där z' är punkten i koordinatytan som vi skall transformera oss till, z är koordinaten i orginalmodellen av flygplanet, q är normalvektorn som används till rotationenen, s är skalningsfaktorn och p motsvarar den vita pilen på bilden ovan som är platsen vi vill att flygplanets mittpunkt skall befinna sig i. Om du nu jämför den här formeln med den på till exempel sidan om mandelbrotmängden så förstår du varför jag ansträngt mig med att skriva en artikel om vektorgeometri på en site som beskriver hur man skapar fraktaler :-)

: Då hugger vi in på "Grand finale" och utför konststycket :
Räkna index från 0 till antal_punkter
  Sätt t Till o · objekt_x [index] - p · objekt_y [index] : Rotera x, spara i temp
  Sätt t Till t * s                                       : Skala x
  Sätt t Till t + vit_x                                   : Translera x
  Sätt ty [index] Till o · objekt_y [index] + p · objekt_x [index] : Rotera y
  Sätt ty [index] Till ty [index] * s                     : Skala y
  Sätt ty [index] Till ty [index] + vit_y                 : Translera y
  Sätt tx [index] Till t                                  : Flytta temp till x
Nästa index
: Eller som ovan allt i en enda operation :
Räkna index från 0 till antal_punkter
  Sätt t Till ( o · objekt_x [index] - p · objekt_y [index] ) * s + vit_x
  Sätt ty [index] Till ( o · objekt_y [index] + p · objekt_x [index] ) * s + vit_y
  Sätt tx [index] Till t
Nästa index
: Sedan skrivs flygplanet in i bilden på samma sätt vid Visa ovan men vi använder dom
  transformerade tx [i] och ty [i] i stället för orginalen objekt_x [i] och objekt_y [i] :

Om vi nu animerar den vita vektorn och hela tiden flyttar den en liten bit så kommer flygplanet att flytta på sig med nosen ständigt pekandes mot punkten som den gula vektorn pekar på, animerar vi även den så kan man om man styr upp det på rätt sätt få det att se ut som planet är på ytflykt. Att beskriva hur även det går till ligger klart utanför ranmarna för Fractalus men om du är intresserad så finns det en uppsjö av sidor på nätet som beskriver både grundläggande och avancerad vektorgeometri, pröva med google vetja!

Här kan du ladda ner en prekompilerad version av ett Q-Basic program som jag skrev för att testa funktionerna jag beskrivit här. Programmet kräver 80x286 / 80x387, VGA och en PC-DOS miljö för att fungera (funkar alltså även fint från Windows 3.11 & Win9x). Vill du ha lite insikt i hur man överför det här till tre dimensioner så kan du alltid gå till susningsidan där Q-basic beskrivs. Där finns en komplett källkod till en 3D-vektor demo som jag skrivit och även där finns det en prekompilerad version att ladda ner.


Ytflygsplanets fraktala avbildning.

Se även :

Vektorgeometri, Normal, Skalning, Rotation, Föregående sida