Anda di halaman 1dari 133

Kvaternik s alkalmazsuk

Ormai Lrnt

KOSSUTH KIAD

Kvaternik s alkalmazsuk

TARTALOM
Alapok A kvaterni meghatrozsa Kvaterni alapmveletek Tovbbi kvaterni-mveletek Kvaternik szorzatnak abszolt rtke Trbeli forgats kvaternival Kvaternik hrmas szorzata A forgat kvaterni kt vektorkvaterni szorzata Homogn koordintk F# modul: Kvaterni_mveletek Trbeli szerkesztsek ( F# ) Trbeli alakzatok lersa homogn koordintkkal Kvaternik programozott megjelentse ( F# ) Hasb forgatsa (Visual Basic program) Skidom forgatsa (Visual Basic program) Segdmennyisgek a szablyos testek rajzolshoz Programozsi szerkezetek a szablyos testekhez ( F# ) A szablyos testek szerkesztsnek programozsa ( F# ) Konkv testek rajzolsa Elforgatott pontokbl a forgatsi tengely s szg meghatrozsa Konvergencia-fraktlok sszefoglals 1 1 2 9 12 13 19 21 23 26 51 57 63 67 74 78 82 85 111 116 120 129

Kvaternik s alkalmazsuk Alapok


Elektronikus knyvknt mr olvashat A komplex szmok elemi alkalmazsai cm munkm. Annak ismerett ennek az anyagnak a megrtshez feltteleztem. A Wikipdia kvaternik szcikkn kvl Tth Szilvia gnes Kvaternik cm, szintn az interneten fellelhet dolgozatt hasznltam fel az albbiakhoz. Persze a komplex szmokrl szl anyaghoz hasonlan ebben a lersban is igyekeztem az ismeretterjeszts szintjn maradni.

A kvaterni meghatrozsa
A kt sszetevbl ll komplex szmok (amelyeknl a szorzs a komplex szmskon val elforgatst eredmnyez) mintjra trbeli forgatsra kereste a szmok kiterjesztst Hamilton, r matematikus. 1843-ban rjtt arra, hogy a ngy komponens kvaterni lehet a megolds a problmjra. Ltni fogjuk, hogy kvaternikkal vgzett mveletek tnyleg megvalsthatnak trbeli elforgatst. Felismerse szerint a vals 1 egysg sszetevt kiegszt msik hrom (vele s egymssal ssze nem vonhat) sszetevnek egysgre a kvetkez sszefggseknek kell teljeslnik:

Ebbl persze tovbbi balrl, illetve jobbrl szorzsokkal kvetkezik, hogy:

A szorzs asszociativitst (csoportosthatsgt) feltteleztk. Viszont ltszik, hogy a szorzs nem kommutatv (felcserlhet), hiszen a bal oldalon a tnyezket felcserlve a jobb oldal eljelet vlt. A fenti kt kpletsorra a tovbbiakban a kvaterni egysgek szorztbljaknt hivatkozunk. (Nem szerepel itt a vals 1 egysg: hiszen brmelyik egysget akr balrl, akr jobbrl a vals 1 egysggel szorozzuk, az rtke nem vltozik.) A vals, illetve a komplex szmokhoz hasonlan a kvaterniknl is vizsglhatnnk a test-aximk teljeslst: mivel a szorzs nem kommutatv, a kvaternik csupn ferdetestet alkotnak. A tovbbi kpleteinkben a nem kiemelt ll betkkel valsakat, a flkvr dlt betkkel kvaternikat (ritkn de akkor felhvjuk r a figyelmet komplex szmokat) jellnk. A vektor mennyisgeket flkvr, ll, fellhzott betvel klnbztetjk meg. A szorzst tbbnyire a * jellel * nyomatkostjuk. De fels index jel a konjugls jele is. (Megjegyezzk, hogy sokfle szorzst jellnk ugyanazzal a * jellel: skalrok vals szmok egymssal szorzst; kvaternik egymssal szorzst; kvaternik valssal szorzst; vektorok valssal szorzst. Mindig az operandusok, amelyekkel a szorzst el kell vgezni, mutatjk, hogy milyen szorzs mveletrl van sz. De vals szmok egymssal szorzst jelljk egyms mell rssal is.)

Kvaternik s alkalmazsuk
A kvetkez bekezdsben felrjuk a kvaternik legltalnosabb, ngy sszetevbl ll alakjt. Most csak megemltjk, hogy maguk a vals szmok is kvaternik, amelyeknek a kpzetes rszk (a hrom tovbbi sszetevjk) 0. Kvaternik a fenti egysgek is, ezeknek (mint kvaterniknak) is a msik hrom sszetevje 0. Termszetesen, a csak vals komponenst tartalmaz kvaternikon a kvaterni alapmveleteket vgrehajtva az eredmny sszetevi kzl ismt csak a vals sszetev mrtke lesz 0 -tl eltr. A vals egysg s (pldul) az egysg ltal meghatrozott szmsk a szoksos komplex szmsk. A komplex szmskhoz tartoz kvaternikon (amelyeknek teht a s egysghez tartoz sszetevi 0-k) vgzett kvaterni alapmveletek nem vezetnek ki a komplex szmskbl (hiszen mg az kvaterniszorzat is a maga -es eredmnyvel ezen a szmskon bell marad). De ugyangy hasznlhatjuk a vals egysg s a egysg ltal kifesztett szmskot vagy a vals egysg s a egysg ltal kifesztett szmskot komplex szmskknt (hiszen -re s -ra egyarnt az nmagval val szorzs eredmnye). A tovbbiakban az anyagban ltalnosan hasznlt s betjel kvaterni szerkezett (a komplex analgijra az algebrai alakot) mutatjuk az sszetevik szoksos megjellsnek bevezetsvel: A jobb oldali tmr rsmddal azt mutatjuk, hogy a kvaterni ngy dimenzis terben egy dimenzit a vals rsz -szel, tovbbi hrom dimenzit pedig egy, a msik hrom bzis egysg ( egysg kvaterni, amelyeket pronknt egymsra merleges egysgvektoroknak tekintnk) ltal kifesztett eredvel, a kpzetes rsz -szel adhatunk meg. ( A kpzetes rsz teht hromdimenzis vektor. ) s kvaternik egyenlsghez a ngy sszetev mrtknek egyenlsge szksges, azaz

Kvaterni alapmveletek
A komplex szmokhoz hasonlan a kvaternikon is rtelmezhetnk egy- s ktoperandus mveleteket. Az egyoperandus mveletek kzl a negls (ellentett kpzs) itt is valamennyi sszetev eljelt ellenkezjre vltja. Konjugls sorn pedig csak a vals rsz nem vlt eljelet (a kpzetes rsz a vektor eljelet vlt): A szorzsi inverz (reciprok) kpzsnek lersra itt is (kvaternik esetn is) ksbb kerl sor.

Kvaternik s alkalmazsuk

Kvaternik s alkalmazsuk
A ktoperandus mveletek kzl az sszeadst s a kivonst (a komplex szmokhoz hasonlan) sszetevnknt vgezzk el. Az sszeads s a kivons (ennek a mveletvgzsi szablynak is ksznheten) termszetesen felcserlhet (kommutatv) s csoportosthat (asszociatv). ( ( ( ) ( ) ( ) ) ( ) ( ( ) ( ) ) ( ) )

A kvaternik szorzshoz kiktjk a disztributivitst is (teht sszeget tagonknt szorozhatunk). ( ) ( )

A szorzsokat tagonknt elvgezve (alkalmazva az els oldalon bemutatott szorztblt):

A szorzs eredmnyt kvaterni-sszetevk szerint rendezve:

( ( (

) ) )

sszevonhatunk tagokat gy, hogy megfelelen csoportostva felismerhetnk pr szerkezetet: ( ( ( ) ( ) ( ) ( ) ( ) ) )

teht ( zrjelprba zrva kln a vals, kln a kpzetes rszt ): ( ) ( )

Ebben a kpletben a kt kvaterninak a hrom, kpzetes sszetevje ltal meghatrozott vektor skalris szorzata ( jellse: ) s vektorilis szorzata ( jellse: ) szerepel:

Kvaternik s alkalmazsuk
( ) ( | | ) ( )

A vektorok prhuzamossga esetn:

a vektorok merlegessge esetn pedig:

. A vektorok prhuzamossga termszetesen akkor is teljesl, ha a kvaternit s ): ( ) nmagval (vagy a konjugltjval) szorozzuk (

Ha a kvaternit a sajt konjugltjval szorozzuk: ( ) ( )

akkor az eredmny vals, hiszen az albbi szorzsi eredmny zrjelezett, msodik rsze : ( )

gy megkaptuk a kvaterni abszolt rtknek (normjnak) a ngyzett: | |

Teht a norma, a kvaterni abszolt rtke: | | .

Csak megjegyezzk, hogy egy kvaterninak s a konjugltjnak az sszege is vals: ( A vals szmok ( ) ( )

) tekinthetk olyan kvaterniknak, amelyeknek a kpzetes rsze :

Olyan kvaternik szorzata, amelyeknek csak vals rszk van (a kpzetes rszk ): a vals rszek szorzata. Ha , illetve , akkor Ha a kvaternik vals rsze 0 ( , illetve ), akkor

Vagyis tisztn kpzetes kvaternik esetn a kvaterni szorzat a vektorok skalris s vektorilis szorzatbl ll el, mghozz gy, hogy a szorzat kvaterni vals rsze a vektorok skalris szorzatnak ellentettje, mg a szorzat kvaterni kpzetes rsze a vektorok vektorilis szorzata. (A fenti mveleteknl lthattuk, hogy a szorzsoknl csak a kpzetes kvaterni egysgek: s egyms kztti sorrendjre kellett gyelnnk, hiszen ezek egymssal nem felcserlhetek. Viszont a kvaternik sszetevinek mrtkeit, az egysgek mell rt vals szmokat a szorzatok elejre kigyjthetjk, egymssal sszeszorozhatjuk.)

Kvaternik s alkalmazsuk
( ( A tovbbiakban kvaternik sszeszorzsnl, pldul a ) ) szorzat meghatrozsnl ksrtst rznk arra, hogy azt mondjuk, kttagt kttagval kell szorozni, ebben semmi klnleges nincs, kapunk ngy szorzatot, azokat sszeadjuk. Azaz: ( ) ( )

Eddig minden rendben van, igaz. De itt emlkeztetnnk arra, hogy a jel kvaterni-szorzs mveletet jelent! A kvaterni-szorzs nem klnbzik a szokott szorzsoktl mindaddig, amg kt vals szmot kell sszeszorozni ( ) illetve, amikor ( akr kvaterni egysgek lineris kombincijaknt felptett ) vektort kell skalrral, egy vals szmmal szorozni: ilyenkor ugyanis mindegyik vektor-sszetev mrtkt megszorozzuk a skalrral, a vals szmmal. Ez a helyzet a illetve a esetben. Ms a helyzet a tagnl. Figyelem! Ez a mvelet nem kt vektor skalris szorzata, de nem is kt vektor vektorilis szorzata! Itt a kt vektor kvaterni-szorzatrl van sz! A kvaterni-szorzat kiszmtsnl pedig a kvaterni-szorztbla ( #Szorztbla ) szerint kell eljrnunk. Vagyis: ( ) ( )

A bzis kvaterni-egysgekbl alkotott vektorok kvaterni-szorzata egy kvaterni, amelynek vals rsze a vektorok skalris szorzatnak ellentettje, kpzetes rsze pedig a vektorok vektorilis szorzata. Oka ennek a kvaternik szorztblja: a hrom tagbl ll vektorok tagonknti sszeszorzsnl kt klnbz bzisegysg sszeszorzsakor az eredmny (#Jobbsodrs_rendszer) a kettre merleges harmadik bzis egysg (vagy ellentettje); kt megegyez bzis egysg szorzata pedig a vals . (Korbban sem tettk, a tovbbiakban sem fogjuk, csupn ezen az oldalon klnbztettk meg a kvaterni-szorzst a tbbi szorzstl azzal, hogy a szorzsi mveleti jelet piros csillagknt rtuk. A kvaterni egysgekkel felptett vektorok elrejtik a vektor kvaterni voltt, erre mutattunk itt r.)

Kvaternik s alkalmazsuk
A kvaternik egysg eleme (a szorzsi egysg) az , azaz a vals 1 szm. Kvaternik hnyadosnak ellltshoz nzzk a reciprok (szorzsi inverz) meghatrozst! Ehhez ) ) ( ) elszr beltjuk, hogy ( hiszen ( -nek teljeslnie kell. De a szorzs asszociativitsa (csoportosthatsga) miatt ez a ( ) ( ) ( )

vgrehajts esetn teljesthet. Tegyk fel, hogy kvaterni abszolt rtke nem 0, azaz nem a nulla kvaterni ( ), amely minden sszetevjnek mrtke 0. (Abban az esetben ugyanis nem ltezik a reciprok.) | |

Ennek a kvaterninak a reciprokt keressk! Ehhez balrl egy egysgnyi szorzattal bvtjk, majd az asszociativits (csoportosthatsg) miatt a tnyezket mskpp zrjelezzk: ( ) ( ) ( )

(Kihasznltuk, hogy a kiindulsi felttel szerint.) A reciprok teht a konjuglt osztva az abszolt rtk ngyzetvel. Lthat, hogy egysg kvaterni (1 abszolt rtk kvaterni) reciproka a konjugltja. Az oszts mvelett ezek utn gy definilhatjuk, hogy az osztandt az oszt reciprokval jobbrl szorozzuk (ha az oszt abszolt rtke nem nulla): | | | | | |

Teht az oszt konjugltjval (jobbrl) val szorzs eredmnyt az oszt abszolt rtke ngyzetvel kell elosztani (pontosan gy, mint a komplex oszts esetn). Nullval nem lehet osztani. Ha | | , akkor a | Ha a -vel megegyez irny egysg kvaterni: | | | | | | | | |

kvaternit a vals rsz s a hromdimenzis kpzetes vektor sszegeknt nzzk, azaz: | | ( | | | | )

akkor mivel a zrjelen belli rsz egysg kvaterni ( ezrt tallhat olyan | | ) ( || ) | | ( amelyre )

szg,

Kvaternik s alkalmazsuk
|| | |

ezzel a kvaterni trigonometrikus alakjt felrhatjuk: | | ( || ) | | ( )

Itt teht szerepel egy egysgvektor, s ha az abszolt rtkkel nem szorozzuk egy egysg kvaterni. Az egysg kvaterni trigonometrikus alakja:

A kvaternik trigonometrikus alakjhoz mskpp is eljuthatunk. (A tovbbiakban a tisztn kpzetes kvaternikat vektorkvaterniknak is nevezzk, hiszen ezek vektorok, amelyekre kvaternimveletek rtelmezettek.) Kpezzk kt vektorkvaterni szorzatt ( #Tisztn_kpzetesek_szorzata ): ( ) ( )

Ha a s a vektor ltal kzrezrt szg || ||

akkor a skalris s a vektorilis szorzatukat trhatjuk: || ||

Ugyanis kt vektor skalris szorzata egy vals szm: a kt vektor abszolt rtknek s a kzrezrt szgk koszinusznak a szorzata. Kt vektor vektorilis szorzata vektor, amelynek irnya mindkt szorztnyezre merleges, nagysga (abszolt rtke) pedig a kt vektor abszolt rtknek s a kzrezrt szg (ez a szg az ramutat jrsval ellenttesen pozitv) szinusznak a szorzata. Vgezzk el a lehetsges talaktsokat! Kihasznlva, hogy kvaterniszorzat abszolt rtke a tnyezk abszolt rtknek szorzata ( #Szorzat_abszolt_rtke ); a tisztn kpzetes kvaterni abszolt rtke megegyezik vektornak abszolt rtkvel; vgl vektorok vektorilis szorzata mindkt szorztnyezre merleges s ebben a sorrendben: a jobb kz hvelyk-, mutat- s kzps ujja ltal formlthoz hasonl, jobbsodrs rendszert alkot: | | | | || ||

( )

Ha a s szge, akkor s szge Teljesl r, hogy: Ez a vektorkvaternik szorzatbl ellltott egysgkvaterni trigonometrikus alakja. sszefoglalva: | Ltezik olyan | | | | | ( ) ( ( ) )

szg, amelyre

Kvaternik s alkalmazsuk Tovbbi kvaterni-mveletek


Most kvaternikkal olyan mveleteket mutatunk, amelyekre nem lesz felttlenl szksgnk a tovbbiakban. (Ezeknek az sszefggseknek a levezetst nem a hasznlhatsguk indokolja minden esetben. Tbbszr csupn azt szeretnnk megmutatni, hogy jabb s rgebbi matematikai mennyisgeink kztt klnbz mdon teremthetnk kapcsolatot.) Pldul a szorzatban ( #Kvaternik_szorzsi_szablya ) szerepel vektorilis szorzat rsz kiszmtsra vezetnk le egy kvaterni-sszefggst. Felrjuk a s szorzatot: ( ( ) ) ( ( ) )

Itt is rmutatunk arra, hogy ha fennllna a szorzs kommutativitsa (a tnyezk felcserlhetsge), a fenti kt szorzat jobb oldala egymssal megegyezne, ahogyan legtbb tagjban meg is egyezik. gy viszont a fentiek klnbsge (kihasznlva, hogy a valsok szorzata s a skalris szorzat a tnyezk felcserlsvel nem vltozik, a vektorilis szorzat viszont eljelet vlt): ( )

A kvaterni-szorzat a tnyezk felcserlsekor a vektorilis szorzatrsz dupljval mdosul. Teht a kvaterniknak a (vals rszen kvli) vektor sszetevik vektorilis szorzata gy is szmolhat: ( ) ( ) illetve ( ) ugyanis: )

Kt kvaterni ngydimenzis skalris szorzata: ( a szorzatbl csak a vals rszt meghatrozva ( ( Persze, ugyanezt kapjuk ( )

fggvny a kvaterni vals rszt adja vissza ):

) kiszmtsakor is. kvaternin bemutatva ): ) ( )

Kvaternik sszetevi az albbi kpletek szerint vlaszthatk le ( ( ) ( ) (

De a konjuglt hozzadsval is levlaszthatjuk az egyes sszetevk mrtkt:

Kvaternik s alkalmazsuk
A konjuglst a kvaternin vgzett egyszer algebrai mveletekkel is lerhatjuk. Ehhez a

sszeadva a jobb oldali egyenleteket ltszik, hogy:

A komplex szmok olyan kvaterniknak is tekinthetk, amelynl a sszetev 0.

bzishoz tartoz

a kvaterni-szorzatot kpezve lthatjuk, hogy az sszetevkkel kifejezve ppen a komplex szorzs eredmnyt adja: ( ) ( )

( Hasonlkppen a tovbbiakban is ltni fogjuk, hogy a kvaternikkal s a komplex szmokkal kapcsolatos sszefggseink (formlisan) megegyeznek.

Kvaternik ngyzetgykt is kiszmolhatjuk. Az sszefggsek levezetshez felttelezzk, hogy kvaterni a kvaterni ngyzetgyke. Teht:

A korbbiakban ( #Kvaterni_ngyzete ) meghatroztuk

-t, eszerint:

10

Kvaternik s alkalmazsuk

Ebbl a

sszetevire vonatkozlag a kvetkez egyenleteket nyerjk:

Az els egyenletet

-nel szorozva s 0-ra rendezve:

majd behelyettestve a fenti, tovbbi sszetevkre vonatkoz sszefggseket:

| |

| |

A kt kvaterni-ngyzetgyk egyms ellentettje, hiszen mindegyik sszetev mrtke eljelet vlt. A msodfok megold kplet gykjele eltt (a norma eljeleknt) csak a pozitv eljelet alkalmazzuk, mivel p0 -ra csak vals szmot keresnk. Errl persze esznkbe juthat, hogy ugyangy kellene a komplex gykvonst is megvalstani! Teht:

Ha c s d ismert, hatrozzuk meg a-t s b-t!

ez utbbibl: | | | |

Azaz a kvaternikra kapott kpletek pontos megfelelihez jutottunk. Megjegyezzk, hogy a vals, ezrt a gykjel alatt csak a + eljel elfogadhat. gy a vgs kpletek: | |

A kt komplex ngyzetgyk ppen egyms ellentettje (ahogyan azt ms mdon is megkaptuk). Mindenesetre sokkal egyszerbb gy, mint a komplex szm trigonometrikus alakjbl kiindulva!

11

Kvaternik s alkalmazsuk Kvaternik szorzatnak abszolt rtke


Szorzat abszolt rtke az abszolt rtkek szorzata. Ugyanis, ha a kt kvaterni:

akkor abszolt rtkk ngyzete: | | | |

Ezek szorzata: ( ) ( )

Ugyanakkor a szorzat abszolt rtknek ngyzete a szorzat sszetevinek ngyzetsszege: ( ( ( ( ) ) ) )

Itt a ktszeres szorzatok sznezsvel kvntuk belttatni, hogy ezek pronknt kiesnek. Csak a ngyzetes tagok maradnak meg, amelyek viszont a fentivel sszehasonltva jl lthat megegyeznek a tnyezk abszolt rtknek szorzatnl kiszmtott eredmnnyel.

12

Kvaternik s alkalmazsuk
Az abszolt rtkekre vonatkoz szorzsi szablybl levonhat az a kvetkeztets, hogy ha az albbi kpletekben mindegyik bet nemnegatv, egsz szmot jell, akkor: ( ( ) ( ) ) ( ( ) ) ( )

Teht: ha kt pozitv egsz szm egyike s msika is ngy nemnegatv, egsz szm ngyzetnek sszege, akkor a kt termszetes szm szorzata is ngy ngyzetszm sszege. (Mivel bebizonythat, hogy minden prmszm felrhat nem felttlenl egyrtelmen ngy nemnegatv, egsz szm ngyzetnek sszegeknt, ezrt a fenti ttel kvetkezmnye az, hogy minden termszetes szm ngy nemnegatv, egsz szm ngyzetnek sszegeknt rhat fel: ez Lagrange ngy ngyzetszm ttele. Akit a ttel teljes bizonytsa rdekel, az a http://tassyg.web.elte.hu/2005-2006-2/szamelmelet3.pdf anyagban keresse a kvetkezt: 4 ngyzetszm.)

Trbeli forgats kvaternival


Egy adott egysg komplex szmmal val szorzst a komplex szmsk egy alakzatnak valamennyi pontjra alkalmazva az alakzat (torztsmentes) elforgatst eredmnyezi. A kvaternival szorzs a disztributivitsbl kvetkezen lineris transzformci, ezrt remlhetjk hogy eredmnyre jutunk amikor azt keressk, hogy milyen kvaterni-szorzssal (szorzsokkal) tudjuk a trbeli alakzatokat torztsmentesen elforgatni. Viszont problmnk, hogy a kvaternik szorzsa nem kommutatv: ms eredmnyt kapunk, ha egy kvaternival balrl, mst, ha jobbrl szorzunk meg egy msikat. Gondolatmenetnk a kvetkez: felttelezzk, hogy az elforgatst vgre tudjuk hajtani, s a tisztn kpzetes kvaternit elforgatva kvaterni volna az eredmny. Az ilyen tisztn kpzetes kvaternik kpzetes rsze ltal meghatrozott hromdimenzis trben kifesztett kocka forgats rvn ugyanannak a trnek egy msik, hozz hasonl kockjba menne t. A tnyleges forgats vgrehajtsba gy fogunk, hogy a kocka mindegyik sarokponti kvaternijt egy kvaternival balrl megszorozzuk. Viszont az gy nyert j kvaternik ltal kifesztett alakzatot nem kocknak, hanem ferde hasbnak tapasztaljuk. (Radsul ennek a ferde hasbnak a cscsai nem tisztn kpzetesek, a hasb kilg a kpzetes, hrom dimenzis trbl.) Hasonlkppen: ha a -vel jellt sarokpont kocka mindegyik sarokponti kvaternijt ugyanazon kvaternival jobbrl szorozzuk, akkor az gy nyert j kvaternik nem lesznek tisztn kpzetesek, s az ezen kvaternik ltal kifesztett alakzat ugyancsak nem kocka, hanem ferde hasb lesz. A ferde hasbot az elforgatsi ksrletnkben olyan kzbens llapotnak tekintjk, amely a balrl s jobbrl szorzs sorn a kockbl kockba val tmenet sorn elll.

13

Kvaternik s alkalmazsuk

Ekkor a ferde hasb nek, illetve nek megfelel pontjra igaz az, hogy ez a sarokpont kvaternival balrl szorzottja, illetve ez a sarokpont kvaternival jobbrl szorzottja:

Mindkt oldalt jobbrl

nel szorozva kifejezhetjk az elforgatott kvaternit:

A fentiekben vzolt gondolatmenetnek megfelelen egy tisztn kpzetes kvaterni elforgatsnl balrl egy kvaternival, jobbrl ugyanennek a kvaterninak a reciprokval kell szorozni. Egysg kvaterni esetn viszont a reciprok a konjuglttal azonos. Ezrt az egyszerbb szmols rdekben a tovbbiakban a fenti transzformcinl kvaterni gyannt mindig egysg kvaternit alkalmazunk. (Az egysg kvaterni lttuk gy rhat: ) Megjegyezzk, hogy t a kvaterni szgnek, t pedig a kvaterni tengelynek nevezzk. A alakban felrhat ( )

tisztn kpzetes kvaternik vektorn az albbi ktoldali szorzsi mvelet

tengely krli

szggel val elforgatst jelent (forgatsi transzformci).

14

Kvaternik s alkalmazsuk
Szigoran vve ezt az lltst nem bizonytjuk, de tbb lpsben megmutatjuk, hogy tapasztalataink altmasztjk a helyessgt. Nzzk meg elszr, mit eredmnyez, ha a fenti mveletet az tengely irnyba mutat ( ), tisztn kpzetes kvaternira alkalmazzuk ( #Kvaternik_szorzsi_szablya ): ( ( ) ( ) ( ) ( ) )

Vagyis ahogyan azt forgats esetn vrjuk is a tengelyre es pontok nem vltoznak. Nzznk kt, azonos ( ) tengely, alkalmazsval megvalstott elforgatst: ( ) ( ) ( egysg kvaterni egyms utni ) ( ) ) ( ) ( ) ))

A #Kvaternik_szorzsi_szablya ( ( a fenti, bal oldali kt tnyez szorzatra alkalmazva: ( ( ) ) (

Hasonlkppen a jobb oldali kt tnyez szorzatra alkalmazva: ( ( ) ) ( ( ) szg elforgatst jelent: ( ) ( ) , akkor a )

Vagyis az egyms utn alkalmazott kt elforgats egyetlen, ( ) ( )

Vagy legyen a forgat kvaterni tengelye ppen forgat kvaterni:

a kvaterni szge ( )

(Joggal jegyezhetik meg, hogy az egysg kvaterni kpletben a kpzetes rsz mrtke mellett egy egysgvektor szerepel, a fenti kpletben pedig a egysg kvaterni. Ezt gy kell rteni, hogy vektor.) A forgatst az ( ) egysg ltal meghatrozott kvaternin vgezzk el (a szorztbla szerint): ( ) ( ) ( -t ) -be viszi t.

Valban: a

tengely krl

szg forgats

15

Kvaternik s alkalmazsuk
ltalnosan alkalmazzuk a tisztn kpzetes kvaternira (azaz kvaternira ) az egysg kvaternival val forgatst amely rvn a kvaterniba megy t! Teht a forgats tengelye: a forgats szge azaz a forgat kvaterni: ( ) ( ) ( )

A bal oldali kvaterni-szorzst vgrehajtva ( #Kvaternik_szorzsi_szablya ): Az jabb kvaterni-szorzs eredmnye: (( ) ( ) ) ( ) ( ) ( ) ( )

Az ( ) vegyesszorzat ( a hrom vektor ltal kifesztett parallelepipedon trfogata ) 0, mert kt vektor azonos benne. Az ( ) szorzatra pedig, amely ppen a vektor egysgvektorra merleges sszetevje, a kifejtsi ttelt ( http://ttmk.nyme.hu/mtmi/Documents/ Vektorok s gmbi geometria vgs.pdf ) alkalmazzuk: ( )

(A levonand vektor -vel prhuzamos sszetevje.) ( )

Ezeket behelyettestve: ( )

( )

Ez az sszefggs a tisztn kpzetes kvaterninak az egysg kvaternival vgzett elforgatsra egyszer szmtsi lehetsget nyjt. Lthat a fenti sszefggsbl: egyrszt, hogy az elforgatott kvaterni is tisztn kpzetes; msrszt, hogy a msodik tag kiesik, ha vektor -re merleges, a harmadik tag pedig akkor , ha vektor az elforgats tengelyvel prhuzamos. Az elforgats szge ezrt is clszer a fenti egyenletbe a ktszeres szgekre vonatkoz trigonometriai sszefggseket berni: ( ) ( )

A kvaterninak megfelel vektor egy irny, egy irny ( ppen vektornak az irny sszetevje) s egy mindkettre merleges ( ) sszetevbl ll.

16

Kvaternik s alkalmazsuk
Jobban megrthet ennek a kpletnek a jelentse is, ha bevezetjk a felbontst, ahol a forgatsi tengellyel ( ) prhuzamos, pedig az arra merleges sszetevt jelenti. ( amelyben ) ( ) ( )

figyelembevtelvel s nmi trendezssel vilgos kpet kapunk: ( )

A prhuzamos sszetev vltozatlan marad, a merleges sszetev Pldul a korbbi forgatsi pldnkban ( ) ( )

szggel elfordul. Akkor

Ha vektor -re merleges, akkor (ahogyan fl oldallal korbban is kiaddott): ( )

ahol a jobb oldali msodik tagban szerepel vektor ( ) abszolt rtke megegyezik | | kel, irnya pedig az re merleges skban van s -re merleges. kt komponense ppen a szggel elforgatott vektort hatrozza meg. (Az bra ezt az esetet mutatja.)

17

Kvaternik s alkalmazsuk
Ha vektor -vel prhuzamos, akkor (a kplet utols eltti vltozatbl elhagyva a vektorilis szorzatos tagot, amely ekkor termszetesen ): ( Ha vektor vel prhuzamos, akkor ( ) | | ) || gy behelyettestve:

Teht az vel prhuzamos vektorok nem vltoznak. Nem hagyott nyugodni a krds: mi van akkor, ha a forgatsi transzformci al vetett kvaterni nem tisztn kpzetes, azaz alak! (Magyarn: tbb pontbl ll alakzat esetn a sarokpontokhoz tartoz kvaternik vals rszt nullzni kell-e azeltt, mieltt a szorzsi transzformcit alkalmaznnk, mert klnben az alakzat az elforgats kvetkeztben eltorzul?) Alkalmazzuk kvaternira az egysg kvaternival val ( az tengely krli szg ) forgatst amely rvn a kvaterniba megy t! Kpletnk kiss mdosul: ( ) ( ) ( )

A bal oldali kvaterni-szorzst vgrehajtva (a jobb oldali szorzst tovbbra is csak jelljk):

Most a jobb oldali kvaterni-szorzst ( #Kvaternik_szorzsi_szablya ) is elvgezzk:

( Az ( ) ( ) ( ( (( ) ) ) szorzat a )

) vegyesszorzat ismt 0 ( mert kt vektor azonos ). Az ( ) kifejtsi ttel szerint ismt: ( )

A skalris szorzatoknl nyilvn: ezrt kt egyms melletti tag kiesik. A vektorilis szorzatoknl pedig a tnyezk felcserlse eljelvltst eredmnyez, ezrt kt tagot sszevonunk:

18

Kvaternik s alkalmazsuk

( )

Vgl lthatjuk, hogy csak annyi a vltozs, hogy

hiszen

Teht a kvaterni vals rszre az elforgats nem hat, s a vals rsz rtktl fggen nem vltozik az elforgatott kvaterni kpzetes rsze ( #Tisztn_kpzetes_forgatsa ). A vals rsz egyegy rtkhez tartoz hromdimenzis trbl a forgatsi transzformci sem vezet ki. ( Tudjuk, hogy a vektormveletek nem vezetnek ki, hiszen azoknak nincs kzk a kvaterni vals rszhez. )

Kvaternik hrmas szorzata


Ez a fejezet tulajdonkppen nem nyjt j ismereteket, ezrt annak, aki gyorsan kvn informldni a kvaternikrl, aki ennek az anyagnak a lnyegt kvnja csak ttekinteni, nem kell vele foglalkoznia. Annak, hogy mgis bekerlt ez a fejezet is az anyagba, az az oka, hogy bizonytsuk: igenis van rtelme a levezetseknek akkor is, ha a szmtgpes kirtkelseket nem az ilyen mdon tmrtett, s ttekinthetv tett kpletekkel vgezzk! Egyrszt gy ismtelten meggyzdhetnk levezetett eredmnyeink helyessgrl; msrszt aki ilyen levezetseket nyomon kvet, jrtassgra tesz szert, s knnyebben tud jabb, hasonl sszefggsekre bukkanni. Legyen hrom kvaterni, a szokott s

Az els kett sszeszorzst nem kell jra elvgeznnk, elg a #Kvaternik_szorzsi_szablya alapjn szorzatukat idemsolnunk (a harmadik szorzs mg csak kijellve): ( ) ( )

A kijellt kvaterniszorzst is ugyanezen szably alapjn hajtjuk vgre:

( ) (

( )

vegyesszorzat a hrom benne szerepl vektor ltal kifesztett parallelepipedon trfogata. Ez 0, ha a hrom vektor kzl legalbb kett prhuzamos.

19

Kvaternik s alkalmazsuk
( ) szorzatra ismt a kifejtsi ttelt alkalmazzuk: ( )

A kifejtsi ttel szerint feloldjuk a a ktszeres vektorszorzatot:

( ) ( )

Kicsit tcsoportostva ezt tekinthetjk a hromtnyezs kvaterniszorzat kpletnek:

( ) ( ( )

) )

( ( Ekkor )

Alkalmazzuk ezt a kpletet arra az esetre, amikor

( ( ( || ) )

|| ) (

) ( )

A vegyesszorzat s az utols vektorszorzat nyilvnvalan , teht a (forgatsi transzformcira emlkeztet) hrmas kvaterniszorzat: ( || ) ( || ) ( )

A szorzat kvaterni vals rsze , megszorozva | | tel, a kvaterni abszolt rtke ngyzetvel; kpzetes rsze , irny, s e kettre merleges ( ) sszetevbl ll. Az ltalunk alkalmazott forgat kvaternikat egysgnyi abszolt rtknek vlasztottuk, amelyek trigonometrikus alakja: ahol egysgvektor a forgats tengelynek irnyt jelli ki (a tengely mindig tmegy az orign), pedig a forgats szgnek fele. Ha ezt a kvaterni helyett bevezetjk, akkor lthatjuk, hogy ppen a kvaterni abszolt rtknek ngyzete. Msrszt || hiszen ez .

20

Kvaternik s alkalmazsuk
Ezeket behelyettestve: ( ) ( )

Ismt a korbbi eredmnynket kaptuk (termszetesen). Ismt lerjuk a kpletet a ktszeres szgekkel is: ( ) ( )

A forgat kvaterni kt vektorkvaterni szorzata


A kvaternik trigonometrikus alakjnak msodik megvilgtsnl ( #Vektorkvaternik_szorzata ) forgat kvaternit ( #Forgat_kvaterni ) lltottunk el, amely a kt vektorra merleges tengely ) ( ) krl ( szggel ( ) forgat: ( ) ( ) ( )

Ugyanerre az eredmnyre jutunk, ha elszr a vektorbl ellltott vektorkvaternival, majd a vektorbl kpezett tisztn kpzetes egysgnyi vektorkvaternival forgatunk, hiszen: ( ) ( ) ( ) ( | )

A fenti kpletben egy tetszleges kvaterni, erre alkalmazzuk az elforgatst. A forgat kvaterni pedig kt (egysgnyi abszolt rtk) vektorkvaterni szorzata. A kt vektor egymshoz viszonytott hajlsszge a forgatsi szg fele. A kt vektorkvaterni sszeszorzsakor elll a forgat kvaterni szokott alakja: a forgat kvaterni vals rsze a forgatsi szg felnek koszinusza, a forgat kvaterni kpzetes rsze a forgatsi szg felnek szinuszval szorozva egy mindkt vektorra merleges egysgvektor ( ), amely (teht a kt vektor vektorilis szorzatnak egysgvektora). A forgats a kt vektorkvaternival egyms utn vgrehajtott forgatsi transzformciknt is megvalsthat. Teht a forgat kvaternit nem felttlenl szksges a fenti (explicit) alakjban meghatrozni, a forgats a kt vektor ismeretben mr vgrehajthat. Csak megjegyezzk, hogy minden vektorkvaterni vel forgat, azaz tengelyesen tkrz forgat kvaterni. Meg is felel a forgat kvaternik szoksos felrsnak: ( ) ( ) hiszen ( ) ( )

Teht kt vektorkvaternival egyms utn vgrehajthatunk kt forgatsi transzformcit. Az els transzformci tkrzst jelent az els vektor ltal (orign tmenen felvett) tengelyre. Ugyangy, a msodik forgatsi transzformci is tkrzst eredmnyez a msodik vektor ltal (ugyancsak orign tmenen felvett) tengelyre. Az eredmny az eredeti alakzat olyan elforgatsa, amely a kt vektor

21

Kvaternik s alkalmazsuk
eredje ltal meghatrozott tengely krl trtnik, s szge a kt vektor szgnek duplja. A vektorilis szorzsnl a tnyezket felcserlve a szorzat eljelet vlt. Ez az alapja annak, hogy a forgat kvaternit ltrehoz vektorvaternik alkalmazsnak sorrendjt megcserlve a forgats irnya ellenkezjre vltozik.

Az brn piros drtvz a kiindulsi kocka. Ha ezt elszr az ltal meghatrozott tengelyre majd az ltal kijellt tengelyre tkrzzk, a zldes sznezs kockkhoz jutunk. Ugyanaz a vgllapot (narancs sznezs), ha a kt vektorkvaternit sszeszorozzuk ( ) s az vektorral prhuzamos tengely krl forgatunk. Ha viszont elszr az tengelyirnyra tkrznk, akkor kiindulsul a pspklila kockhoz jutunk. Ezt az ltal meghatrozott tengelyre tovbb tkrzve az elbbitl eltr a vgllapot, viszont ugyanoda (trkiz szn) jutunk, ha a kt vektorkvaternit

22

Kvaternik s alkalmazsuk
fordtott sorrendben sszeszorozzuk ( ) s az

vektorral prhuzamos tengely krl

forgatunk. (A pldban a kt vektor hajlsszge 60, az ered vektor krli elforgats szge 120.) A kt vgllapot (a trkiz, illetve narancs sznnel sznezett) a kiindulsi llapotbl egyazon, orign tmen forgatsi tengely krl vgzett ellenkez irny forgatssal ll el (hiszen csupn a vektorok sorrendjt cserltk meg, ezrt a forgatsi tengelyt a kt esetben egymssal prhuzamos, de ellenttes irny vektor jelli ki).

Homogn koordintk
A kvaternit a hromdimenzis tr homogn koordints lekpezsnl is hasznlhatjuk. A hromdimenzis tr [ x, y, z ] koordintj pontjhoz ugyanis az [ 1, x, y, z ] homogn koordintkat rendelhetjk. ( Ugyanehhez a ponthoz tartozik a [ , * x, * y, * z ] koordintangyes is, ahol tetszleges vals szm. A homogn koordintk az arnyossg erejig meghatrozottak.) A kvaterni azrt clszer eszkz a hromdimenzis tr homogn koordints lersra, mert ppen ngy vals koordintartket trol. Megjegyzs: A kiegszt homogn koordintt a trkoordintk mg szoktk negyedikknt berni. Mivel mi a kvaternik vals sszetevjt, amelyet a kvaterniban els sszetevknt szerepeltetnk, kvnjuk erre a clra felhasznlni, ebben az anyagban a kiegszt koordintt rjuk az els helyre. Az interneten bsgesen tallhatnak anyagokat a homogn koordintk kifejezsre kerestetve. De tanulmnyozhatjk a http://www.agt.bme.hu/szakm/szg/homogen.htm anyagot is, amelyet a tma kifejtsnl leginkbb kvettem. Kiindulskppen a ktdimenzis esetet tekintjk t. A skbeli kp pontjai kt koordintjnak a pontokon s a vettsi kzpponton thalad sugrra illeszked trbeli pontok homogn koordinti valamennyien megfelelnek. (A mlysgi koordinta elvesztsvel ll el a kp az ernyn.) Elmleti oldalrl nzzk a skbeli koordintaprrl a homogn koordintkra val ttrs menett! A koordintk szmt eggyel megnveljk. Kznsges (vges) pont esetn a kiegszt koordinta rtkl egy nulltl eltr szmot adunk meg. Az 1 szmrtk koordintval val kiegszts azzal az elnnyel jr, hogy ekkor a msik kt koordinta szmrtkt nem kell megvltoztatni. A kiegszt koordinta rtke 0 is lehet, de akkor a homogn koordintahrmas egy idelis pontot jell ki a skon, amely tulajdonkppen a maradk kt koordinta ltal meghatrozott irny. (Az idelis pontok a vgtelen tvoli pontok. Prhuzamos egyenesek sokasghoz ugyanaz az idelis pont tartozik. Ezrt is mondjk, hogy az idelis pontok mindegyike valjban egy irny.) Mind a hrom koordinta egyszerre 0 nem lehet: ilyen rvnyes homogn koordinta nincs. A skbeli egyenes megszokott egyenlett formra trva lthatjuk, hogy az egyenes egyenlete (skalris szorzat) alakban is rhat, ahol az egytthatk vektora, pedig az egyenes pontjait kijell

23

Kvaternik s alkalmazsuk
(homogn) koordintavektor. Az egyenes egytthatvektornak s a pont koordinta-vektornak a skalris szorzata (flsk-fggen eljelezve) arnyos a pontnak az egyenestl mrt tvolsgval, s 0 abban az esetben, ha a pont az egyenesre illeszkedik. (A fenti talaktssal az egyenes egyenlethez tartoz egytthatvektor az egyenes normlisa: az egyenes homogn koordintavektorukkal adott pontjai erre merlegesek.) Az egyenesnek a fenti, 0-ra rendezett egyenletbl nyilvnvalan ltszik, hogy ha vektor megadott rtke kielgti az egyenletet, akkor brmely vals szmmal szorzott rtke is megfelel. Innen a nv: a homogn koordintknak ez az arnyossg erejig val meghatrozottsga a homogenits. Ha az egyenesnek kt, egymstl klnbz pontjt, az s pontot nzzk, akkor a s egyenletnek is teljeslnie kell, vagyis . (Ha egy vektor kt egymssal nem prhuzamos vektorra merleges, akkor a kt vektor vektorilis szorzatval prhuzamos.) Ekkor pedig az egytthatkat a vektorilis szorzat els sorban felsorolt egysgvektorok egytthatiknt (az ezekhez a pontokhoz tartoz eljeles aldeterminnsokknt) szmthatjuk, ugyanis prhuzamos vektorok egytthati csak egy kzs szorzban klnbzhetnek: | ( | )

Most nzzk a hasonl mveleteket a hromdimenzis krnyezetben! A hromdimenzis tr kznsges pontjaihoz hozzrendelt homogn koordintk ngy sszetevbl llnak, amelyek kzl hrom a korbbi, hromdimenzis trbeli koordinta, a negyedik szmrtke pedig 1 (br mind a ngyet tetszleges szmmal szorozhatjuk, vagy tetszleges szmmal el is oszthatjuk). Termszetesen a trbeli esetben is ltezik olyan homogn koordinta, amelynl a negyedik koordintartk 0, ez ebben az esetben is egy vgtelen tvoli, idelis pontot jelent, amely valjban a msik hrom koordinta mint vektor ltal meghatrozott irny. (Tulajdonkppen a kvaternikkal ezt pontosan gy rthetnnk: ha a vals rsz 0, a kpzetes rsz vektora ltal meghatrozott irnyt jelenti a kvaterni.) Nem ltezik ngy 0 rtkkel lert homogn koordinta. A hromdimenzis tr skjnak egyenlett a kvetkez kplettel adhatjuk meg:

A sk egyenlete alakban is rhat, ahol az egytthatk vektora, pedig a sk pontjait kijell (homogn) koordintavektor. A sk fenti egyenletbl kvetkezen a sk egytthatvektornak s egy pont koordintavektornak a skalris szorzata 0 abban az esetben, ha a pont a skra illeszkedik. (A sk egyenlethez tartoz egytthatvektor a sk ngydimenzis normlisa: a sk pontjai homogn koordintjukkal erre merlegesek.) Ha a sknak hrom pontjt, az a pontot nzzk, akkor a a s a s a

24

Kvaternik s alkalmazsuk
( ) egyenletnek is teljeslnie kell, vagyis ( ). (Itt az jells a hrom vektor ngydimenzis vektorilis szorzatra vonatkozik, amely a hrom felhasznlt vektor irnyra merleges.) A ktdimenzis vektorilis szorzat mintjra ennek determinnsa: ( ) | |

Az egytthatkat a determinns els sorban felsorolt egysgvektorok egytthatiknt szmthatjuk, az ezekhez tartoz eljeles aldeterminnsok az (arnyossg erejig meghatrozott) egytthatk: ( ( ( ( ) ) ) ) ( ( ( ( ) ) ) ) ( ( ( ( ) ) ) )

Korbbi jellsnkhz visszatrve a sk egytthatibl alkotott kvaterni s a sk egy pontja homogn koordintit tartalmaz kvaterni felhasznlsval a sk egyenlete ( #Skalris_szorzat_4 ): ( )

Ha van hrom, kvaternijval adott pontunk:

akkor (mivel a fenti egyenlsgnek mindhrom ponttal teljeslnie kell) az albbi ngydimenzis vektorilis szorzat eredmnyvel kell a sk ngydimenzis vektornak prhuzamosnak lennie:

a fenti determinns els sorhoz tartoz eljeles aldeterminnsoknak kell d, a, b, c-nek megfelelnie. ( ( ) ) ( ( ) ( ( ( ) ) ) ( ( ) ( ) ) ( ) )

Kzi szmtsnl ezt az egyszerbb kpletet hasznlhatnnk. Szmtgpen viszont az ltalnosan rvnyes, a lap tetejn lthat kpletet programoztam ( Kvaterni_mveletek VectProd4 ). gy a ngydimenzis vektorilis szorzat kplete a skok metszsponjnak meghatrozsra is mkdni fog.

25

Kvaternik s alkalmazsuk F# modul: Kvaterni_mveletek


Az elz fejezetekben lthat talaktsok, egyszerst sszevonsok egyrszt segtenek megrteni a kvaterni-kifejezsek mkdst, msrszt igen megknnytik a kzi szmolst. Valjban ma mr senki nem fog kvaternikkal vgzett szmtsokba szmtgp nlkl. Akkor viszont hiszen a mai szmtgpeink mr olyan nagy teljestmnyek nem az sszevonsok lehetsge, hanem a kvaterni osztly s az osztly pldnyain vgezhet mveletek teljeskr programozsa lnyeges. Nagy jelentsge van a programozsi nyelv korszersgnek, amely okbl pldul a Microsoft F# (efsrp) nyelve vlasztand. Hangslyozzuk, hogy ma mr a programjainkat akr modulonknt is eltr nyelven rhatjuk, gy az albbi programmodult is ms nyelven rt programokba is importlni lehet. (Pldul Visual Basic nyelv programokba is, ahogyan kt, ksbbi fejezetben lthat.) // Kvaterni osztly deklarlsa s alkalmazsa module Kvaterni_mveletek open System let let let let let let let let let let let let let let let let let let let let let let let let let let let let public public public public public public public public public public public public public public public public public public public public public public public public public public public public NULLA = double 0.0 FL = double 0.5 EGY = double 1.0 MINEGY = - EGY MSFL = double 1.5 KETT = double 2.0 KTSFL = double 2.5 HROM = double 3.0 HARMAD = EGY / HROM PI = double Math.PI NGY = double 4.0 NEGYED = EGY / NGY T = double 5.0 TD = EGY / T HAT = double 6.0 HATOD = EGY / HAT HT = double 7.0 NYOLC = double 8.0 KILENC = double 9.0 TZ = double 10.0 TIZED = EGY / TZ TIZENKETT = double 12.0 TIZENT = double 15.0 HSZ = double 20.0 HUSZONT = double 25.0 HARMINC = double 30.0 HARMINCHAT = double 36.0 HATVAN = double 60.0 // Gyakran hasznlt llandk

26

Kvaternik s alkalmazsuk
let let let let let public public public public public HATVANAD = EGY / HATVAN HETVENKETT = double 72.0 NYOLCVAN = double 80.0 SZZ = double 100.0 SZZNYOLCVAN = double 180.0

let public FOKBLV = Math.PI / SZZNYOLCVAN let public VBLFOK = SZZNYOLCVAN / Math.PI let let let let let public public public public public GYKKETT = Math.Sqrt(KETT) GYKHROM = Math.Sqrt(HROM) GYKT = Math.Sqrt(T) GYKKETTPERKETT = GYKKETT / KETT GYKHROMPERKETT = GYKHROM / KETT

let public PICINY = double 0.0000000001 let public SEMMI = double 1e-14 let public VGTELEN = Double.PositiveInfinity

// A kvaterni kpzetes rsze 3 dimenzis vektor - ezt rjuk le itt: type public Vector(iRsz: double, jRsz: double, kRsz: double) = class // A vektor sszetevi: member vektor.iComp = iRsz member vektor.jComp = jRsz member vektor.kComp = kRsz // A vektor hossza: member vektor.abs = Math.Sqrt( iRsz * iRsz + jRsz * jRsz + kRsz * kRsz) // Vektor nyjtsa (illetve zsugortsa, ha a nyjts < 1.0): member vektor.Scal( nyjts : double ) = Vector( iRsz * nyjts, jRsz * nyjts, kRsz * nyjts) // Vektor egysgvektora: member vektor.Unit = let oszt = vektor.abs if oszt < PICINY then Vector() else Vector(iRsz / oszt, jRsz / oszt, kRsz / oszt)

27

Kvaternik s alkalmazsuk
// Kt vektort egyenlnek tekint ez a mvelet, ha egy irnyba // mutatnak, azaz ha egysgvektoraik egyenlk: static member (=) ( U: Vector, V: let Ue = U.Unit let Ve = V.Unit Math.Abs(Ue.iComp - Ve.iComp) Math.Abs(Ue.jComp - Ve.jComp) Math.Abs(Ue.kComp - Ve.kComp) // Vektorok sszege (U + V): static member (+) ( U: Vector, V: Vector ) = Vector( U.iComp + V.iComp, U.jComp + V.jComp, U.kComp + V.kComp ) // Vektorok klnbsge (U - V): static member (-) ( U: Vector, V: Vector ) = Vector( U.iComp - V.iComp, U.jComp - V.jComp, U.kComp - V.kComp ) // Vektorok vektorilis szorzata (a vektorok "termszetes" // sszeszorzsa - az eredmny is vektor): static member (*) ( Vector( U.jComp U.kComp U.iComp U: Vector, V: Vector ) = * V.kComp - U.kComp * V.jComp, * V.iComp - U.iComp * V.kComp, * V.jComp - U.jComp * V.iComp) Vector ) : bool =

< PICINY && < PICINY && < PICINY

// Vektorok skalris szorzata: static member dotProd( U: Vector, V: Vector ) = U.iComp * V.iComp + U.jComp * V.jComp + U.kComp * V.kComp // Hatrozatlan (nulla) vektor: new() = Vector(NULLA, NULLA, NULLA) end // A kvaterni osztly deklarlsa: type public Kvaterni( vals: double, iMrtk: double, jMrtk: double, kMrtk: double) = class // A kvaterni sszetevinek mrtke: member pldny.re = vals

28

Kvaternik s alkalmazsuk
member pldny.imI = iMrtk member pldny.imJ = jMrtk member pldny.imK = kMrtk // Kvaterni kpzetes rsze vektor alakban: member pldny.Vect = Vector( iMrtk, jMrtk, kMrtk ) // Kvaterni abszolt rtknek ngyzete: member pldny.abs2 = vals * vals + iMrtk * iMrtk + jMrtk * jMrtk + kMrtk * kMrtk // Kvaterni abszolt rtke (hossza): member pldny.abs = Math.Sqrt(pldny.abs2) // // // // Kvaterni trigonometrikus alakjra utalva az egysg kvaterni kpzetes rsznek mrtke, a kvaternihoz tartoz egysgvektort ezzel megszorozva ll el a (vektor) kpzetes rsz:

member pldny.sin = if pldny.abs < PICINY then NULLA else pldny.Vect.abs / pldny.abs // Kvaterni trigonometrikus alakjra utalva az egysg // kvaterni vals rsznek mrtke: member pldny.cos = if pldny.abs < PICINY then NULLA else vals / pldny.abs // Kvaterni konjuglsa: member pldny.Konj = Kvaterni( vals, -iMrtk, -jMrtk, -kMrtk ) // Kvaterni nyjtsa vagy zsugortsa: member pldny.Scal( nyjts : double ) = Kvaterni( vals * nyjts, iMrtk * nyjts, jMrtk * nyjts, kMrtk * nyjts) // Egysg kvaterni kpzse: member pldny.Unit = let oszt = pldny.abs if oszt < PICINY then Kvaterni() else Kvaterni( vals / oszt, iMrtk / oszt, jMrtk / oszt, kMrtk / oszt )

29

Kvaternik s alkalmazsuk
// Egy kvaterni pldny trigonometrikus alakja szerint // adja vissza az vhosszban mrt szget: member pldny.arc = if pldny.abs < PICINY then NULLA elif pldny.Vect.abs < PICINY then Math.PI else Math.Acos(pldny.cos) // Kt kvaterni egyenl, ha komponensenknt megegyeznek: static member (=) ( P: Kvaterni, Q: Kvaterni ) : bool = Math.Abs(P.re - Q.re) < PICINY && Math.Abs(P.imI - Q.imI) < PICINY && Math.Abs(P.imJ - Q.imJ) < PICINY && Math.Abs(P.imK - Q.imK) < PICINY // Kvaterni sszeads: a szokott mdon lerva az sszeads // jele eltt ll kvaternihoz hozzadja a + jel utni // kvaternit (P + Q ): static member (+) ( P: Kvaterni, Q: Kvaterni ) = Kvaterni( P.re + Q.re, P.imI + Q.imI, P.imJ + Q.imJ, P.imK + Q.imK ) // Kvaterni kivons: a kisebbtendbl kivonja a // kivonandt ( P - Q ): static member (-) ( P: Kvaterni, Q: Kvaterni ) = Kvaterni( P.re - Q.re, P.imI - Q.imI, P.imJ - Q.imJ, P.imK - Q.imK ) // Kvaterni szorzs: a szorzs jele eltti kvaternit // szorozza a * jel utn ll kvaternival ( P * Q ): static member (*) ( P: Kvaterni, Q: Kvaterni ) = Kvaterni( P.re * Q.re - P.imI * Q.imI P.imJ * Q.imJ - P.imK * Q.imK, P.re * Q.imI + P.imI * Q.re + P.imJ * Q.imK - P.imK * Q.imJ, P.re * Q.imJ + P.imJ * Q.re P.imI * Q.imK + P.imK * Q.imI, P.re * Q.imK + P.imK * Q.re + P.imI * Q.imJ - P.imJ * Q.imI ) // // // // // Kvaterni oszts: az oszts jele eltti kvaternit elosztja a / jel utn ll kvaternival. Vgrehajtsa: az osztandt megszorozza az oszt konjugltjval, majd az gy nyert szorzatot elosztja az oszt abszolt rtke ngyzetvel. Ezrt az oszts akkor vgrehajthat, ha az

30

Kvaternik s alkalmazsuk
// oszt kvaterni nem az O kvaterni (teht, ha az oszt // abszolt rtke nem 0) ( P / Q ): static member (/) (P: Kvaterni, Q: Kvaterni) = let oszt = Q.abs2 if oszt < PICINY then Kvaterni() else Kvaterni(( P.re * Q.re + P.imI * Q.imI + P.imJ * Q.imJ + P.imK * Q.imK) (-P.re * Q.imI + P.imI * Q.re P.imJ * Q.imK + P.imK * Q.imJ) (-P.re * Q.imJ + P.imJ * Q.re + P.imI * Q.imK - P.imK * Q.imI) (-P.re * Q.imK + P.imK * Q.re P.imI * Q.imJ + P.imJ * Q.imI) // // // // //

/ oszt, / oszt, / oszt, / oszt )

Ngydimenzis (kvaterni) skalrszorzat. Homogn koordintj pont s kvaternijval megadott egytthats (egysgvektor kpzetes rsz) sk esetn jl hasznlhat eredmnyt szolgltat. (Skra illeszked pontnl 0, amgy a hromdimenzis trben a sktl mrt tvolsgot adja meg.)

static member dotProd4(P: Kvaterni, Q: Kvaterni): double = (P * Q.Konj).re // // // // // // // // // Ngydimenzis vektorilis szorzat. Hrom kvaternit hasznl 4 x 4 -es determinnsban. Az els sorhoz tartoz eljeles aldeterminnsok rtkt adja vissza kvaterniba rendezve. Ha hrom pont kvaternijval hvjuk, akkor sk egytthatvektort adja vissza gy, hogy a vektor helyn egysgvektor van. (Ha hatrozatlan volna a sk, a homogn koordintaknt nem megengedett O-t adja ki.) Ha skok metszspontjt szmtjuk, a pont vals rsze helyn 1 vagy 0 lesz attl fggen, hogy ltezik-e.

static member VectProd4( P: Kvaterni, Q: Kvaterni, R: Kvaterni ) : Kvaterni = let d = P.imI * ( Q.imJ * R.imK - Q.imK * R.imJ ) P.imJ * ( Q.imI * R.imK - Q.imK * R.imI ) + P.imK * ( Q.imI * R.imJ - Q.imJ * R.imI ) let a = -P.re * ( Q.imJ * R.imK - Q.imK * R.imJ ) + P.imJ * ( Q.re * R.imK - Q.imK * R.re ) P.imK * ( Q.re * R.imJ - Q.imJ * R.re ) let b = P.re * ( Q.imI * R.imK - Q.imK * R.imI ) P.imI * ( Q.re * R.imK - Q.imK * R.re ) + P.imK * ( Q.re * R.imI - Q.imI * R.re ) let c = -P.re * ( Q.imI * R.imJ - Q.imJ * R.imI ) + P.imI * ( Q.re * R.imJ - Q.imJ * R.re ) P.imJ * ( Q.re * R.imI - Q.imI * R.re ) let Kpzetes = Vector( a, b, c )

31

Kvaternik s alkalmazsuk
let oszt = if d < NULLA then Kpzetes.abs else -Kpzetes.abs if Math.Abs( P.re - EGY ) < PICINY && // 3 pont alapjn Math.Abs( Q.re - EGY ) < PICINY && // sk ltrehozsa Math.Abs( R.re - EGY ) < PICINY then if Math.Abs(oszt) < PICINY then Kvaterni() else Kvaterni(d, Kpzetes).Scal( EGY / oszt ) else // Hrom sk metszspontjnak meghatrozsa: if Math.Abs(d) < PICINY then Kvaterni(NULLA,Kpzetes) else Kvaterni( EGY, Kpzetes.Scal( EGY / d ) ) // Kt homogn kvaterni (arnyossg erejig) egyenl, ha // egysgkvaterniik komponensenknt megegyeznek: static member HomogeneousEqual( P: Kvaterni, Q: Kvaterni ): bool = let Pe = P.Unit let Qe = Q.Unit Math.Abs(Pe.re - Qe.re) < PICINY && Math.Abs(Pe.imI - Qe.imI) < PICINY && Math.Abs(Pe.imJ - Qe.imJ) < PICINY && Math.Abs(Pe.imK - Qe.imK) < PICINY // Kvaterni ltrehozsa a kpzetes rsz vektor alakjval: new( val: double, vektor: Vector) = Kvaterni( val, vektor.iComp, vektor.jComp, vektor.kComp ) // // // // Kvaterni ltrehozsa, amely a V (orign tmenen felvett) vektor (mint tengely) krl fok szggel forgat (az elforgatand kvaternit balrl ezzel a kvaternival, jobbrl pedig ennek a konjugltjval kell szorozni).

new( V : Vector, fok: double ) = let v = fok * FOKBLV / KETT Kvaterni( Math.Cos(v), V.Unit.Scal(Math.Sin(v)) ) // Hatrozatlan (nulla) kvaterni: new() = Kvaterni( NULLA, NULLA, NULLA, NULLA ) end // Kvaterni llandk: let public O = Kvaterni() // Vals egysg. Homogn koordintknl ez a nulla pont: let public Base0 = Kvaterni( EGY, NULLA, NULLA, NULLA )

32

Kvaternik s alkalmazsuk
// Homogn koordintknl I tengely vgtelen tvoli pontja: let public BaseI = Kvaterni( NULLA, EGY, NULLA, NULLA ) // Homogn koordintknl J tengely vgtelen tvoli pontja: let public BaseJ = Kvaterni( NULLA, NULLA, EGY, NULLA ) // Homogn koordintknl K tengely vgtelen tvoli pontja: let public BaseK = Kvaterni( NULLA, NULLA, NULLA, EGY ) // Kvaterni ngyzetgykvons: let public Ngyzetgyk ( Szm : Kvaterni) : ( Kvaterni * Kvaterni ) = let vals = Math.Sqrt( ( Szm.re + Szm.abs ) / KETT ) let nevez = KETT * vals if Math.Abs(nevez) < PICINY then ( O, O ) else ( Kvaterni( vals, Szm.imI / nevez, Szm.imJ / nevez, Szm.imK / nevez ), Kvaterni( -vals, -Szm.imI / nevez, -Szm.imJ / nevez, -Szm.imK / nevez ) )

// Az albbi konstruktoroknl pontokat vagy a hrom koordinta // felsorolsval, vagy kvaterniknt lehet megadni. A vektorokat // soha nem kvaterniknt, hanem csakis Vector-knt adjuk meg. // Egyenesszakasz lersa: type public Section( Kezdet: Kvaterni, Vg : Kvaterni ) = class // Ha a Kezdet s a Vg vals rsze nem azonos, nincs // rtelme a szakasznak, pontjai nincsenek ugyanabban a // trben: let egyVilgban = Math.Abs( Kezdet.re - Vg.re ) < PICINY member szakasz.Pont1 = if egyVilgban then Kezdet else O member szakasz.Pont2 = if egyVilgban then Vg else O member szakasz.hossz = ( szakasz.Pont2 - szakasz.Pont1 ).abs // Paramter nlkl is hatrozatlan a szakasz: new() = Section( O, O ) end

33

Kvaternik s alkalmazsuk
// Hromszg osztly lersa: type public Triangle( A : Kvaterni, B : Kvaterni, C : Kvaterni ) = class // Ha a A, B s C vals rsze nem azonos, nincs rtelme // a hromszgnek, pontjai nincsenek ugyanabban a trben: let egyVilgban = Math.Abs( B.re - A.re ) < PICINY && Math.Abs( C.re - A.re ) < PICINY member alakzat.Acscs = member alakzat.Bcscs = member alakzat.Ccscs = if egyVilgban then A else O if egyVilgban then B else O if egyVilgban then C else O

member alakzat.Cscsok : Kvaterni array = [| alakzat.Acscs; alakzat.Bcscs; alakzat.Ccscs |] member alakzat.aHossz = ( alakzat.Ccscs - alakzat.Bcscs ).abs member alakzat.bHossz = ( alakzat.Ccscs - alakzat.Acscs ).abs member alakzat.cHossz = ( alakzat.Bcscs - alakzat.Acscs ).abs member alakzat.kerlet = alakzat.aHossz + alakzat.bHossz + alakzat.cHossz member alakzat.terlet = let flK = Math.Sqrt( ( ( ( alakzat.kerlet / KETT flK * flK - alakzat.aHossz ) * flK - alakzat.bHossz ) * flK - alakzat.cHossz ) )

member alakzat.szablyos : bool = Math.Abs( alakzat.aHossz - alakzat.bHossz ) < PICINY && Math.Abs( alakzat.bHossz - alakzat.cHossz ) < PICINY && Math.Abs( alakzat.cHossz - alakzat.aHossz ) < PICINY // A cscsok megadsa nlkl is hatrozatlan a hromszg: new() = Triangle( O, O, O )

34

Kvaternik s alkalmazsuk
// A cscsok lerhatk kvaternik hrom elem tmbjvel is: new( Cscsok : Kvaterni array ) = if Cscsok.Length = 3 then Triangle( Cscsok.[0], Cscsok.[1], Cscsok.[2] ) else Triangle() end // Ngyszg osztly lersa: type public Quadrangle( A : Kvaterni, B : Kvaterni, C : Kvaterni, D : Kvaterni) = class // Ha a A, B, C s D vals rsze nem azonos, nincs rtelme // a ngyszgnek, pontjai nincsenek ugyanabban a trben: let egyVilgban = Math.Abs( B.re - A.re ) < PICINY && Math.Abs( C.re - A.re ) < PICINY && Math.Abs( D.re - A.re ) < PICINY member alakzat.Acscs = member alakzat.Bcscs = member alakzat.Ccscs = member alakzat.Dcscs = if egyVilgban then A else O if egyVilgban then B else O if egyVilgban then C else O if egyVilgban then D else O

member alakzat.Cscsok : Kvaterni array = [| alakzat.Acscs; alakzat.Bcscs; alakzat.Ccscs; alakzat.Dcscs |] member alakzat.hosszAB = ( alakzat.Bcscs - alakzat.Acscs ).abs member alakzat.hosszBC = ( alakzat.Ccscs - alakzat.Bcscs ).abs member alakzat.hosszCD = ( alakzat.Dcscs - alakzat.Ccscs ).abs member alakzat.hosszDA = ( alakzat.Acscs - alakzat.Dcscs ).abs member alakzat.kerlet = alakzat.hosszAB + alakzat.hosszBC + alakzat.hosszCD + alakzat.hosszDA

35

Kvaternik s alkalmazsuk
member alakzat.terlet = let hosszAC = ( alakzat.Ccscs - alakzat.Acscs ).abs let terlet( a: double, b:double, c: double) = let s = ( a + b + c ) / KETT Math.Sqrt( s * (s - a) * (s - b) * (s - c) ) terlet( alakzat.hosszAB, alakzat.hosszBC, hosszAC ) + terlet( alakzat.hosszCD, alakzat.hosszDA, hosszAC ) member alakzat.szablyos : bool = Math.Abs( alakzat.hosszAB - alakzat.hosszBC Math.Abs( alakzat.hosszBC - alakzat.hosszCD Math.Abs( alakzat.hosszCD - alakzat.hosszDA Math.Abs( alakzat.hosszDA - alakzat.hosszAB

) ) ) )

< < < <

PICINY && PICINY && PICINY && PICINY

// A cscsok megadsa nlkl is hatrozatlan a ngyszg: new() = Quadrangle( O, O, O, O ) // A cscsok lerhatk kvaternik ngy elem tmbjvel is: new( Cscsok : Kvaterni array ) = if Cscsok.Length = 4 then Quadrangle( Cscsok.[0], Cscsok.[1], Cscsok.[2], Cscsok.[3] ) else Quadrangle() end // tszg osztly lersa: type public Pentagon( A : Kvaterni, B : Kvaterni, C : Kvaterni, D : Kvaterni, E : Kvaterni) = class // Ha a A, B, C, D s E vals rsze nem azonos, nincs // rtelme az tszgnek, pontjai nincsenek ugyanabban a // trben: let egyVilgban = Math.Abs( Math.Abs( Math.Abs( Math.Abs( member alakzat.Acscs = member alakzat.Bcscs = member alakzat.Ccscs = B.re C.re D.re E.re A.re A.re A.re A.re ) ) ) ) < < < < PICINY && PICINY && PICINY && PICINY

if egyVilgban then A else O if egyVilgban then B else O if egyVilgban then C else O

36

Kvaternik s alkalmazsuk
member alakzat.Dcscs = member alakzat.Ecscs = if egyVilgban then D else O if egyVilgban then E else O

member alakzat.Cscsok : Kvaterni array = [| alakzat.Acscs; alakzat.Bcscs; alakzat.Ccscs; alakzat.Dcscs; alakzat.Ecscs |] member alakzat.hosszAB = ( alakzat.Bcscs - alakzat.Acscs ).abs member alakzat.hosszBC = ( alakzat.Ccscs - alakzat.Bcscs ).abs member alakzat.hosszCD = ( alakzat.Dcscs - alakzat.Ccscs ).abs member alakzat.hosszDE = ( alakzat.Ecscs - alakzat.Dcscs ).abs member alakzat.hosszEA = ( alakzat.Acscs - alakzat.Ecscs ).abs member alakzat.kerlet = alakzat.hosszAB + alakzat.hosszBC + alakzat.hosszCD + alakzat.hosszDE + alakzat.hosszEA member alakzat.terlet = let hosszAC = ( alakzat.Ccscs - alakzat.Acscs ).abs let hosszAD = ( alakzat.Dcscs - alakzat.Acscs ).abs let terlet( a: double, b:double, c: double) = let s = ( a + b + c ) / KETT Math.Sqrt( s * (s - a) * (s - b) * (s - c) ) terlet( alakzat.hosszAB, alakzat.hosszBC, hosszAC) + terlet( alakzat.hosszCD, hosszAD, hosszAC) + terlet( alakzat.hosszDE, alakzat.hosszEA, hosszAD) member alakzat.szablyos : bool = Math.Abs( alakzat.hosszAB - alakzat.hosszBC Math.Abs( alakzat.hosszBC - alakzat.hosszCD Math.Abs( alakzat.hosszCD - alakzat.hosszDE Math.Abs( alakzat.hosszDE - alakzat.hosszEA Math.Abs( alakzat.hosszEA - alakzat.hosszAB ) ) ) ) ) < < < < < PICINY PICINY PICINY PICINY PICINY && && && &&

// A cscsok megadsa nlkl is hatrozatlan az tszg: new() = Pentagon( O, O, O, O, O )

37

Kvaternik s alkalmazsuk
// A cscsok lerhatk kvaternik t elem tmbjvel is: new( Cscsok : Kvaterni array ) = if Cscsok.Length = 5 then Pentagon( Cscsok.[0], Cscsok.[1], Cscsok.[2], Cscsok.[3], Cscsok.[4]) else Pentagon() end // Hatszg osztly lersa: type public Hexagon( A : Kvaterni, B : Kvaterni, C : Kvaterni, D : Kvaterni, E : Kvaterni, F : Kvaterni) = class // Ha a A, B, C, D, E s F vals rsze nem azonos, nincs // rtelme a hatszgnek, pontjai nincsenek ugyanabban a // trben: let egyVilgban = Math.Abs( Math.Abs( Math.Abs( Math.Abs( Math.Abs( member alakzat.Acscs = member alakzat.Bcscs = member alakzat.Ccscs = member alakzat.Dcscs = member alakzat.Ecscs = member alakzat.Fcscs = B.re C.re D.re E.re F.re A.re A.re A.re A.re A.re ) ) ) ) ) < < < < < PICINY PICINY PICINY PICINY PICINY && && && &&

if egyVilgban then A else O if egyVilgban then B else O if egyVilgban then C else O if egyVilgban then D else O if egyVilgban then E else O if egyVilgban then F else O

member alakzat.Cscsok : Kvaterni array = [| alakzat.Acscs; alakzat.Bcscs; alakzat.Ccscs; alakzat.Dcscs; alakzat.Ecscs; alakzat.Fcscs |] member alakzat.hosszAB = ( alakzat.Bcscs - alakzat.Acscs ).abs member alakzat.hosszBC = ( alakzat.Ccscs - alakzat.Bcscs ).abs member alakzat.hosszCD = ( alakzat.Dcscs - alakzat.Ccscs ).abs

38

Kvaternik s alkalmazsuk
member alakzat.hosszDE = ( alakzat.Ecscs - alakzat.Dcscs ).abs member alakzat.hosszEF = ( alakzat.Fcscs - alakzat.Ecscs ).abs member alakzat.hosszFA = ( alakzat.Acscs - alakzat.Fcscs ).abs member alakzat.kerlet = alakzat.hosszAB + alakzat.hosszBC + alakzat.hosszCD + alakzat.hosszDE + alakzat.hosszEF + alakzat.hosszFA member alakzat.terlet = let hosszAC = ( alakzat.Ccscs - alakzat.Acscs ).abs let hosszAD = ( alakzat.Dcscs - alakzat.Acscs ).abs let hosszAE = ( alakzat.Ecscs - alakzat.Acscs ).abs let terlet( a: double, b:double, c: double) = let s = ( a + b + c ) / KETT Math.Sqrt( s * (s - a) * (s - b) * (s - c) ) terlet( terlet( terlet( terlet( alakzat.hosszAB, alakzat.hosszCD, alakzat.hosszDE, alakzat.hosszEF, alakzat.hosszBC, hosszAC, hosszAD hosszAD, hosszAE alakzat.hosszFA, hosszAC ) + ) + ) + hosszAE )

member alakzat.szablyos : bool = Math.Abs( alakzat.hosszAB - alakzat.hosszBC Math.Abs( alakzat.hosszBC - alakzat.hosszCD Math.Abs( alakzat.hosszCD - alakzat.hosszDE Math.Abs( alakzat.hosszDE - alakzat.hosszEF Math.Abs( alakzat.hosszEF - alakzat.hosszFA Math.Abs( alakzat.hosszFA - alakzat.hosszAB

) ) ) ) ) )

< < < < < <

PICINY PICINY PICINY PICINY PICINY PICINY

&& && && && &&

// A cscsok megadsa nlkl is hatrozatlan a hatszg: new() = Hexagon( O, O, O, O, O, O ) // A cscsok lerhatk kvaternik hat elem tmbjvel is: new( Cscsok : Kvaterni array ) = if Cscsok.Length = 6 then Hexagon( Cscsok.[0], Cscsok.[1], Cscsok.[2], Cscsok.[3], Cscsok.[4], Cscsok.[5] ) else Hexagon() end

39

Kvaternik s alkalmazsuk
// // // // Egyenesnl s sknl az 1 vals rszhez tartoz trben hozzuk ltre a pldnyokat, minden kvaterninl EGY vals rszt adunk meg. A pontok koordinti gy a pontok homogn koordintjnak felelnek meg.

// Kvaternik (illetve azok vektor kpzetes sszetevje) segtsgvel // vgzett trbeli szerkesztsekhez hasznlt egyenes osztly // deklarlsa (alaphelyzetben kt pontja hat koordintjval): type public Line( i1: double, j1: double, k1: double, i2: double, j2: double, k2: double) = class // Kvaterniknt trolva az egyenes egyik pontja: member egyenes.Point1 = Kvaterni( EGY, i1, j1, k1 ) // Minden esetben trolva ez a msodik pont is: member egyenes.Point2 = Kvaterni( EGY, i2, j2, k2 ) // Az egyenes trolt tulajdonsga az irny egysgvektor // (amelynek hossza hossza 0, ha az egyenes nem ltezik): member egyenes.Vect : Vector = ( egyenes.Point2.Vect - egyenes.Point1.Vect ).Unit // Az egyenes kt pontja a konstruktorban kt kvaternival // is megadhat: new( egyikPont: Kvaterni, msikPont: Kvaterni ) = if Math.Abs(egyikPont.re - msikPont.re) < PICINY then Line( egyikPont.imI, egyikPont.imJ, egyikPont.imK, msikPont.imI, msikPont.imJ, msikPont.imK ) else Line() // Az egyenes kt pontja a pontok szakaszval is megadhat: new( szakasz: Section) = Line( szakasz.Pont1.imI, szakasz.Pont1.imJ, szakasz.Pont1.imK, szakasz.Pont2.imI, szakasz.Pont2.imJ, szakasz.Pont2.imK ) // Megadhat az egyenes egy pontja hrom koordintjval s // az irnyvektor: new( pI: double, pJ: double, pK: double, egyenesIrny: Vector)=

40

Kvaternik s alkalmazsuk
Line( pI, pJ, pI + PI pJ + PI pK + PI pK, * egyenesIrny.iComp, * egyenesIrny.jComp, * egyenesIrny.kComp)

// Az egyenes egy pontja kvaterniknt s az irnyvektor // is ugyangy lerja az egyenest: new( egyenesPont: Kvaterni, egyenesIrny: Vector) = Line( egyenesPont.imI, egyenesPont.imJ, egyenesPont.imK, egyenesPont.imI + PI * egyenesIrny.iComp, egyenesPont.imJ + PI * egyenesIrny.jComp, egyenesPont.imK + PI * egyenesIrny.kComp) // Hatrozatlan egyenes: new() = Line(NULLA, NULLA, NULLA, NULLA, NULLA, NULLA) end // Kvaternik (illetve azok vektor kpzetes sszetevje) segtsgvel // vgzett trbeli szerkesztsekhez hasznlt sk osztly deklarlsa // Egy pontja hrom koordintjval s a normlvektorval: type public Plane( pontI: double, pontJ: double, pontK: double, nVektor: Vector ) = class // A sk trolt tulajdonsga kvaterniknt egyik pontja: member sk.Point = Kvaterni( EGY, pontI, pontJ, pontK ) // A sk normlis egysgvektora (hossza 0, ha a sk nincs): member sk.NormVect = if Vector.dotProd(nVektor, sk.Point.Vect) < NULLA then nVektor.Unit.Scal(MINEGY) else nVektor.Unit // A sk normlvektora krl 60-os forgatst vgz kvaterni: member sk.Rot60Kvat = Kvaterni( GYKHROMPERKETT, sk.NormVect.Scal( FL ) ) // A sk normlvektora krl 72-os forgatst vgz kvaterni: member sk.Rot72Kvat = Kvaterni( sk.NormVect, HETVENKETT )

41

Kvaternik s alkalmazsuk
// A sk normlvektora krl 90-os forgatst vgz kvaterni: member sk.Rot90Kvat = Kvaterni( EGY, sk.NormVect).Scal(GYKKETTPERKETT) // A sk normlvektora krl 120-os forgats: member sk.Rot120Kvat = Kvaterni( FL, sk.NormVect.Scal(GYKHROMPERKETT ) ) // A sk normlvektora krl 180-os forgats: member sk.Rot180Kvat = Kvaterni( NULLA, sk.NormVect )

// A sk pontja (metszspontja vagy vgtelen tvoli pont) // az i tengelyen: member sk.iPoint = if Math.Abs(sk.NormVect.iComp) < PICINY then Kvaterni(EGY, VGTELEN, NULLA, NULLA) else Kvaterni(EGY, Vector.dotProd(sk.Point.Vect, sk.NormVect) / sk.NormVect.iComp, NULLA, NULLA)

42

Kvaternik s alkalmazsuk
// A sk pontja (metszspontja vagy vgtelen tvoli pont) // a j tengelyen: member sk.jPoint = if Math.Abs(sk.NormVect.jComp) < PICINY then Kvaterni(EGY, NULLA, VGTELEN, NULLA) else Kvaterni(EGY, NULLA, Vector.dotProd(sk.Point.Vect, sk.NormVect) / sk.NormVect.jComp, NULLA) // A sk pontja (metszspontja vagy vgtelen tvoli pont) // a k tengelyen: member sk.kPoint = if Math.Abs(sk.NormVect.kComp) < PICINY then Kvaterni(EGY, NULLA, NULLA, VGTELEN) else Kvaterni(EGY, NULLA, NULLA, Vector.dotProd(sk.Point.Vect, sk.NormVect) / sk.NormVect.kComp) // Homogn koordintkat hasznlva ezek a tulajdonsgok: // A sk (kznsges vagy idelis) pontja az i tengelyen: member sk.iHomogeneous = if Math.Abs(sk.NormVect.iComp) < PICINY then BaseI else Kvaterni(EGY, Vector.dotProd(sk.Point.Vect, sk.NormVect) / sk.NormVect.iComp, NULLA, NULLA) // A sk (kznsges vagy idelis) pontja a j tengelyen: member sk.jHomogeneous = if Math.Abs(sk.NormVect.jComp) < PICINY then BaseJ else Kvaterni(EGY, NULLA, Vector.dotProd(sk.Point.Vect, sk.NormVect) / sk.NormVect.jComp, NULLA) // A sk (kznsges vagy idelis) pontja a k tengelyen: member sk.kHomogeneos = if Math.Abs(sk.NormVect.kComp) < PICINY then BaseK

43

Kvaternik s alkalmazsuk
else Kvaterni(EGY, NULLA, NULLA, Vector.dotProd(sk.Point.Vect, sk.NormVect) / sk.NormVect.kComp)

// A sk orighoz legkzelebbi pontja: az origbl a skra // bocsjtott merleges talppontja, a forgatsi tengely pontja member sk.Near = let iTv = sk.iPoint.imI let jTv = sk.jPoint.imJ let kTv = sk.kPoint.imK let ijNevez = iTv * iTv + jTv * jTv let jkNevez = jTv * jTv + kTv * kTv let kiNevez = kTv * kTv + iTv * iTv let ijArny = if ijNevez > PICINY then iTv * jTv / ijNevez else NULLA let jkArny = if jkNevez > PICINY then jTv * kTv / jkNevez else NULLA

44

Kvaternik s alkalmazsuk
let kiArny = if kiNevez > PICINY then kTv * iTv / kiNevez else NULLA let iN = iTv * iTv let jN = jTv * jTv let kN = kTv * kTv let ngyzetek = iN * jN + jN * kN + kN * iN let fArny = if ngyzetek > PICINY then Math.Abs(iTv * jTv * kTv)/Math.Sqrt(ngyzetek) else NULLA if iTv = VGTELEN then if jTv = VGTELEN then sk.kPoint elif kTv = VGTELEN then sk.jPoint else Kvaterni(EGY, NULLA, kTv * jkArny, jTv * jkArny) elif jTv = VGTELEN then if kTv = VGTELEN then sk.iPoint else Kvaterni(EGY, kTv * kiArny, NULLA, iTv * kiArny) elif kTv = VGTELEN then Kvaterni(EGY, jTv * ijArny, iTv * ijArny, NULLA) else Kvaterni(EGY, sk.NormVect.Scal(fArny)) // A sk orighoz legkzelebbi pontja: az origbl a skra // bocsjtott merleges talppontja, a forgatsi tengely pontja member sk.HomogeneousNear = let iTv = sk.iPoint.imI let jTv = sk.jPoint.imJ let kTv = sk.kPoint.imK let ijNevez = iTv * iTv + jTv * jTv let jkNevez = jTv * jTv + kTv * kTv let kiNevez = kTv * kTv + iTv * iTv let ijArny = if ijNevez > PICINY then iTv * jTv / ijNevez else NULLA let jkArny = if jkNevez > PICINY then jTv * kTv / jkNevez else NULLA let kiArny = if kiNevez > PICINY then kTv * iTv / kiNevez else NULLA let iN = iTv * iTv let jN = jTv * jTv let kN = kTv * kTv let ngyzetek = iN * jN + jN * kN + kN * iN let fArny =

45

Kvaternik s alkalmazsuk
if ngyzetek > PICINY then Math.Abs(iTv * jTv * kTv)/Math.Sqrt(ngyzetek) else NULLA if sk.iHomogeneous = BaseI then if sk.jHomogeneous = BaseJ then sk.kPoint elif sk.kHomogeneos = BaseK then sk.jPoint else Kvaterni(EGY, NULLA, kTv * jkArny, jTv * jkArny) elif sk.jHomogeneous = BaseJ then if sk.kHomogeneos = BaseK then sk.iPoint else Kvaterni(EGY, kTv * kiArny, NULLA, iTv * kiArny) elif sk.kHomogeneos = BaseK then Kvaterni(EGY, jTv * ijArny, iTv * ijArny, NULLA) else Kvaterni(EGY, sk.NormVect.Scal(fArny))

// Homogn koordintkkal a skot egy kvaterni rja le, // amelynek kpzetes rsze a sk normlisa, vals rsze pedig // abbl a felttelbl szmthat, hogy a sk tetszleges

46

Kvaternik s alkalmazsuk
// pontja homogn koordintangyesvel a skot ler kvaterni // ngydimenzis skalris szorzata 0. Egybknt ez a vals // rsz az orig (Base0) s a sk tvolsga negatv eljellel. member sk.HomogeneousPlane = Kvaterni( -sk.Near.Vect.abs, sk.Near.Vect.Unit ) // A sk megadhat hrom pontjnak kilenc koordintjval is: new( i1: double, j1: double, k1: double, i2: double, j2: double, k2: double, i3: double, j3: double, k3: double) = Plane( i1, j1, k1, Vector(i3 - i2, j3 - j2, k3 - k2) * Vector(i3 - i1, j3 - j1, k3 - k1) ) // A sk hrom pontja megadhat hromszgknt is: new( hromSzg: Triangle) = Plane( hromSzg.Acscs.imI, hromSzg.Acscs.imJ, hromSzg.Acscs.imK, ( hromSzg.Ccscs.Vect - hromSzg.Acscs.Vect ) * ( hromSzg.Bcscs.Vect - hromSzg.Acscs.Vect ) ) // A sk egy pontja kvaterniknt s a normlvektora is j: new( skPontja: Kvaterni, normlVektor: Vector ) = Plane(skPontja.imI, skPontja.imJ, skPontja.imK, normlVektor) // Egyetlen kvaternival is megadhatjuk a skot, ha ez // a kvaterni a sk homogn koordints lerja: new( homognSk: Kvaterni ) = let oszt = homognSk.Vect.abs let normltSk = if oszt < PICINY then O else homognSk.Scal( EGY / oszt ) Plane( Kvaterni( EGY, normltSk.Vect.Scal( -normltSk.re ) ), normltSk.Vect ) // A sk rgzthet a hrom tengelyen elhelyezked // pontjnak hrom koordintjval (ezek helybe VGTELEN // is rhat, ha a sk az adott tengellyel prhuzamos): new( iPont: double, jPont: double, kPont:double ) =

47

Kvaternik s alkalmazsuk
let iKvaterni = Kvaterni(EGY, iPont, NULLA, NULLA) let jKvaterni = Kvaterni(EGY, NULLA, jPont, NULLA) let kKvaterni = Kvaterni(EGY, NULLA, NULLA, kPont) if iPont = VGTELEN then if jPont = VGTELEN then // A normlvektor k irnyba mutat: Plane(kKvaterni, BaseK.Vect) elif kPont = VGTELEN then // A normlvektor j irnyba mutat: Plane(jKvaterni, BaseJ.Vect) else Plane( kKvaterni, BaseI.Vect * ( jKvaterni.Vect - kKvaterni.Vect ) ) elif jPont = VGTELEN then if kPont = VGTELEN then // A normlvektor i irnyba mutat: Plane(iKvaterni, BaseI.Vect) else Plane( iKvaterni, BaseJ.Vect * ( kKvaterni.Vect - iKvaterni.Vect ) ) elif kPont = VGTELEN then Plane( jKvaterni, BaseK.Vect * ( iKvaterni.Vect - jKvaterni.Vect ) ) else Plane( kKvaterni, ( iKvaterni.Vect - kKvaterni.Vect ) * ( jKvaterni.Vect - kKvaterni.Vect ) ) // Homogn koordints pontmegads esetn (kznsges s // idelis pontokkal) tovbbi lehetsgek knlkoznak: // A sk rgzthet a hrom tengelyen elhelyezked pontjnak // hrom kvaternijval (ezek helybe idelis pont kvaternija // is rhat, ha az adott pont vgtelen tvol van): // iKvaterni = Kvaterni(EGY, iPont, NULLA, NULLA) // vagy: Kvaterni(NULLA, EGY, NULLA, NULLA) - BaseI // jKvaterni = Kvaterni(EGY, NULLA, jPont, NULLA) // vagy: Kvaterni(NULLA, NULLA, EGY, NULLA) - BaseJ // kKvaterni = Kvaterni(EGY, NULLA, NULLA, kPont) // vagy: Kvaterni(NULLA, NULLA, NULLA, EGY) - BaseK // Ha a hrom pont nem tengelypont, akkor is mkdik a // fggvny hrom tetszleges pontra: new( iKvaterni: Kvaterni, jKvaterni: Kvaterni, kKvaterni: Kvaterni ) = if Math.Abs(iKvaterni.imJ) < PICINY && Math.Abs(iKvaterni.imK) < PICINY && Math.Abs(jKvaterni.imI) < PICINY && Math.Abs(jKvaterni.imK) < PICINY &&

48

Kvaternik s alkalmazsuk
Math.Abs(kKvaterni.imI) < PICINY && Math.Abs(kKvaterni.imJ) < PICINY then if iKvaterni = BaseI then if jKvaterni = BaseJ then // A normlvektor k irnyba mutat: Plane(kKvaterni, BaseK.Vect) elif kKvaterni = BaseK then // A normlvektor j irnyba mutat: Plane(jKvaterni, BaseJ.Vect) else Plane( kKvaterni, BaseI.Vect * ( jKvaterni.Vect - kKvaterni.Vect ) ) elif jKvaterni = BaseJ then if kKvaterni = BaseK then // A normlvektor i irnyba mutat: Plane(iKvaterni, BaseI.Vect) else Plane( iKvaterni, BaseJ.Vect * ( kKvaterni.Vect - iKvaterni.Vect ) ) elif kKvaterni = BaseK then Plane( jKvaterni, BaseK.Vect * ( iKvaterni.Vect - jKvaterni.Vect ) ) else Plane( kKvaterni, ( iKvaterni.Vect - kKvaterni.Vect ) * ( jKvaterni.Vect - kKvaterni.Vect ) ) elif Math.Abs(iKvaterni.re - jKvaterni.re) < PICINY && Math.Abs(jKvaterni.re - kKvaterni.re) < PICINY then Plane( iKvaterni.imI, iKvaterni.imJ, iKvaterni.imK, ( kKvaterni.Vect - iKvaterni.Vect ) * ( jKvaterni.Vect - iKvaterni.Vect ) ) else Plane() // Hatrozatlan sk: new() = Plane(NULLA, NULLA, NULLA, Vector() ) end Ebben a modulban nem csupn a Kvaterni osztlyt s az osztly pldnyain vgrehajthat mveleteket hatroztunk meg, hanem tovbbi (segd) osztlyokat is deklarltunk. A homogn koordintk termszetes hasznlatt kvnjuk elsegteni azzal, hogy a kznsges pontokat 1 vals sszetevvel troljuk, tovbb a skok s tulajdonsgaik homogn koordints lerst is tmogatjuk. A Vector osztly deklarlsa a kvaternik kpzetes rsznek tmr lerst szolglja. A Vector osztly pldnyain az sszeadson s kivonson kvl ktfle szorzst: a vektor eredmnyt ad vektorilis szorzst (ezt a mveletet az operandusok szoksos szorzsaknt rhatjuk le), tovbb a vals eredmnyt szolgltat skalris szorzst (angol dot product nevbl: dotProd) is megvalstottunk.

49

Kvaternik s alkalmazsuk
A Kvaterni osztly pldnyain az sszeadst, a kivonst, a szorzst s az osztst is lehetv teszi ez az osztly-deklarci. Tudjuk, hogy a kvaterni-szorzs nem kommutatv, azaz a szorztnyezket nem lehet felcserlni, de a mveleteket (egyik s msik sorrendben is) el lehet vgezni. Az osztst az oszt konjugltjval elvgzett jobbrl szorzsknt rtelmezzk. (Nulla abszolt rtk osztval nem lehet osztani.) A homogn koordintk egyszer kezelse rdekben a kvaterni egyenlsget (valamennyi sszetev egyenlsget vizsgljuk) s a homogn egyenlsget (ekkor csak a kvaternik arnyossgt nzzk) is vizsglhatjuk ennek az osztlynak a fggvnyeivel. Hvhat a ngydimenzis skalris (dotProd4) s vektorilis szorzs (VectProd4) fggvny is. (Utbbi fggvny egyszerv teszi a hrom pontra illeszked sk egyenletnek, illetve a hrom metsz sk metszspontjnak a meghatrozst.) Mivel a kvaternik segtsgvel knny a hromdimenzis tr alakzatait lerni s forgatni, a modul a hromdimenzis trben elvgezhet rajz mveletekhez szksges kt osztly (az egyenes s a sk) deklarcijt is tartalmazza. Itt is megemltjk, hogy a szerkesztsekhez szksges trbeli pontok megadst a homogn koordintikat tartalmaz kvaternikkal vgezzk el, mg a trbeli vektorok lersra a Vector osztly pldnyait hasznljuk. Lttuk, hogy a forgatsi transzformci a kvaterni vals rszt vltozatlanul hagyja, valamint az elforgatott kvaterni vals rsznek sincs hatsa a forgats utni helyzethez tartoz kpzetes rszhez. (Ezrt a forgatsnak alvetett kvaterni vals rszvel nem kell trdni pldul nem kell nullzni, mieltt a kvaternijval adott pontra forgatsi transzformcit alkalmaznnk a homogn koordintt sem teszi rtelmezhetetlenn a forgats.) A skot nagyon egyszer a hrom koordintatengelyen elhelyezked pontjnak megadsval ltrehozni. A sk lehet koordintaskkal vagy tengellyel prhuzamos is, ennek egyszer kezelsre, a tengellyel val metszspont megadsra a VGTELEN rtk is hasznlhat. Valamelyik tengellyel, illetve az egyik koordintaskkal prhuzamos sk ltrehozsnl hasznlhatjuk a homogn idelis pontok rtkt is. (Az tengely vgtelen tvoli pontja BaseI, a j tengely BaseJ, a k tengely pedig BaseK.) Msrszt a skok brzolsnl a normlis egysgvektoruk talppontjaknt az orighoz (illetve a homogn nullhoz: Base0-hoz) legkzelebbi pontjukat (Near, illetve HomogeneousNear) hasznljuk. Ez nagy jelentsg pont, hiszen a forgatsi tengely (az orig mellett, illetve homogn koordints brzolsunknl Base0 mellett) ezen a ponton is keresztlmegy. tfle szghz tartoz forgat kvaternit is kiszmtunk a skok normlis egysg-vektora (mint tengely) krli forgatsra. A homogn koordintk teljeskr bevezetsekppen sk objektumpldnyt tudunk a sk egyenlett ler egytthatngyest tartalmaz kvaternival (egy skkvaternival) is ltrehozni, valamint a sk objektum tulajdonsgaknt lekrdezhet az egytthatkat tartalmaz skkvaterni is. Pontprknt a szakasz, skidomok kzl pedig a hromszg, a ngyszg, az tszg s a hatszg objektumot is lertuk. Ezek deklarcijnl a vals rszkkel is foglalkoztunk annyiban, hogy a bennk szerepl kvaternik mindegyiknek ugyanahhoz a hromdimenzis trhez kell tartoznia, azaz a vals rszeknek azonosaknak kell lennik. Egybknt ugyanis a kvaternik klnbsgnek abszolt rtkeknt megadott oldalhosszak nem a hromdimenzis, hanem a ngydimenzis trben rtend hosszak volnnak. ( Ha egy objektum ltrehozsnl kvaterniknt megadott pontok nem tartoznak egyazon hromdimenzis vilghoz, helyettk -t trolunk: az objektum hatrozatlann vlik. )

50

Kvaternik s alkalmazsuk Trbeli szerkesztsek ( F# )


module public Kvaternis_szerkesztsek open System open Kvaterni_mveletek // // // // // // // // // // // Ez a modul a kvaternik kpzetes rsznek hromdimenzis terben ltrehozott geometriai alakzatok (pontok, egyenesek s skok) segtsgvel elvgezhet szerkesztsek eredmnynek szmtsra szolgl. A Kvaterni_mveletek modulban lert mdon lehet a geometriai alakzatokat ltrehozni: az objektumok tulajdonsgainak lerst is ott talljk. Skon keressk az egyenes dfspontjt. A dfspontot kvaterni kpzetes rszeknt adja vissza. (Ha nincs dfspont, mert az egyenes a skkal prhuzamos, vagy az egyenes a skra illeszkedik, ezrt minden pont dfspont lehetne, a visszaadott kvaterni a vals egysg: Base0 - Homogn koordintkkal a kznsges nulla).

let public SkotDfEgyenes( Sk : Plane, Egyenes : Line ) : Kvaterni = let vetlet = Vector.dotProd(Sk.NormVect, Egyenes.Vect) if Math.Abs(vetlet) < PICINY then Base0 else let lambda = Vector.dotProd( Sk.Point.Vect Egyenes.Point1.Vect, Sk.NormVect ) / vetlet Kvaterni( EGY, Egyenes.Point1.Vect + Egyenes.Vect.Scal(lambda) ) // // // // // Szinte ugyanaz a homogn koordints vltozat. Ekkor a skot egy kvaterni rja le, ennek ngydimenzis skalris szorzatt lehet kpezni az egyenes egyik pontjval (amelytl az egyenes irnyvektornak lambdaszorosra van a dfspont). Ha az egyenes s skkal prhuzamos, a dfspont az egyenes idelis pontja.

let public HomognSkotDfEgyenes( HomognSk : Kvaterni, Egyenes : Line ) : Kvaterni = let oszt = Vector.dotProd(HomognSk.Vect, Egyenes.Vect) if Math.Abs(oszt) < PICINY then Kvaterni(NULLA, Egyenes.Vect) else let lambda = -Kvaterni.dotProd4(HomognSk, Egyenes.Point1) / oszt Kvaterni( EGY, Egyenes.Point1.Vect + Egyenes.Vect.Scal(lambda) ) // Kt sk metszsvonalt hatrozza meg ez a fggvny. Ha a kt sk // prhuzamos (vagy egybeesik), akkor olyan egyenest ad vissza, // amelyik hatrozatlan: mindkt meghatroz pontja a nulla kvaterni.

51

Kvaternik s alkalmazsuk

let public SkokMetszsvonala( Sk1: Plane, Sk2: Plane ) : Line = let metszsvonalVektor = Sk1.NormVect * Sk2.NormVect if metszsvonalVektor.abs < PICINY then Line(O,O) else let skPontja = if (Sk1.Point - Sk1.Near).abs < PICINY then new Kvaterni(EGY,Sk1.Near.Vect + metszsvonalVektor) else Sk1.Point let mutable skbeliEgyenes = new Line(skPontja, Sk1.Near) let mutable dfsPont = SkotDfEgyenes(Sk2, skbeliEgyenes) if dfsPont.Vect.abs < PICINY then let skbeliPont = Sk1.Rot90Kvat * skPontja * Sk1.Rot90Kvat.Konj skbeliEgyenes <- new Line(skbeliPont, Sk1.Near) dfsPont <- SkotDfEgyenes(Sk2, skbeliEgyenes) Line( dfsPont, metszsvonalVektor ) // A skokat ilyenkor egy-egy kvaterni rja le. A Skok kvaterni// jban a komplex vektor rsz a sk hromdimenzis trbeli // normlisa. Ezek vektorilis szorzata most is a metszsvonal

52

Kvaternik s alkalmazsuk
// // // // // // // // // irnyt adja meg. Felvesznk egy harmadik skot a kt skra merlegesen. Mivel ez a sk tetszleges ponton tmen lehet, a skot ler kvaterni vals rszt 1-re lltjuk (ez volna a sk Base0-tl mrt tvolsga). A hrom sk metszspontja a kt sk metszsvonalnak pontja. Ezt s a metszsvonal irnyt felhasznlva a metszsvonal elll. Ha a kt sk egymssal prhuzamos, akkor a skokhoz tartoz vgtelen tvoli egyenes, az idelis egyenes volna a megolds. Ennek pontja a normlis irnyhoz rendelt idelis pont, irnya pedig meghatrozatlan.

let public HomognSkokMetszsvonala ( Sk1: Kvaterni, Sk2: Kvaterni ) : Line = let metszsvonalVektor = Sk1.Vect * Sk2.Vect if metszsvonalVektor.abs < PICINY then Line(Kvaterni(NULLA, Sk1.Vect),Vector()) // prhuzamosak else let Sk3 = Kvaterni(EGY,metszsvonalVektor) let egyenesPontja = Kvaterni.VectProd4(Sk1, Sk2, Sk3) let normltPont = if (egyenesPontja.re - EGY) < PICINY then egyenesPontja else egyenesPontja.Scal( EGY / egyenesPontja.re ) Line( normltPont, metszsvonalVektor )

53

Kvaternik s alkalmazsuk
// Egyenesek egymshoz legkzelebbi pontjnak meghatrozsa. let public EgyenesekTvolsga( Egyik: Line, Msik: Line ) : double = let normlVektor = Egyik.Vect * Msik.Vect if normlVektor.abs < PICINY then // Egy skban a kt egyenes: let ferdeVektor = ( Egyik.Point1 - Msik.Point1 ).Vect let vetletVektor = Egyik.Vect.Scal(Vector.dotProd(Egyik.Vect, ferdeVektor)) let merlegesVektor = ferdeVektor - vetletVektor merlegesVektor.abs else // Kitr egyenesek: let Sk = new Plane(Egyik.Point1, normlVektor) let dfsPont = SkotDfEgyenes(Sk, Line(Msik.Point1, normlVektor)) ( dfsPont - Msik.Point1 ).abs // Egyenesek metszspontjnak meghatrozsa. let public Metszspont( Egyik: Line, Msik: Line ) : Kvaterni = let normlVektor = Egyik.Vect * Msik.Vect if normlVektor.abs < PICINY then Base0 else let Sk = new Plane( Egyik.Point1, Egyik.Vect * normlVektor ) let dfsPont = SkotDfEgyenes(Sk, Msik) if ( dfsPont - Egyik.Point1 ).abs < PICINY then dfsPont elif ( ( dfsPont - Egyik.Point1 ).Vect * Egyik.Vect ).abs < PICINY then dfsPont else Base0 // Egyenesek metszspontjt meghatroz fggvnynk homogn // koordints vltozata (A nem metszk "metszspontja" ms.) let public HomognMetszspont ( Egyik: Line, Msik: Line ) : Kvaterni = let normlVektor = Egyik.Vect * Msik.Vect if normlVektor.abs < PICINY then Kvaterni(NULLA, Egyik.Vect) // prhuzamos egyenesek! else let Sk = new Plane( Egyik.Point1, Egyik.Vect * normlVektor ) let dfsPont = SkotDfEgyenes(Sk, Msik) if ( dfsPont - Egyik.Point1 ).abs < PICINY then dfsPont elif ( ( dfsPont - Egyik.Point1 ).Vect * Egyik.Vect ).abs < PICINY then dfsPont else Kvaterni(NULLA, normlVektor) // kitr egyenesek! // Egy skban megadott (fok) nagysg szg szerkesztse: let public SzgSzerkeszts ( Sk : Plane, fok: Double) : (Line * Line) =

54

Kvaternik s alkalmazsuk
if (Sk.Near - Sk.Point).abs < PICINY then ( Line(O, O), Line(O,O) ) // Hatrozatlan feladat! else let forgatKvaterni = new Kvaterni( Sk.NormVect, fok ) let konjKvaterni = forgatKvaterni.Konj let jPont = forgatKvaterni * Sk.Point * konjKvaterni ( new Line(Sk.Point, Sk.Near ), new Line( Sk.Near,jPont))

// Vektor felbontsa kt sszetevjre. (Paramterknt a vektoron // kvl megadva a felbontsi irnyok egyike vektorknt.) let public sszetevkreBonts ( eredVektor: Vector, egyikVektor: Vector ) : ( Vector * Vector ) = let egyikEgysg = egyikVektor.Unit let prhuzamossszetev = egyikEgysg.Scal(Vector.dotProd(eredVektor,egyikEgysg)) let merlegessszetev = eredVektor - prhuzamossszetev ( prhuzamossszetev, merlegessszetev )

55

Kvaternik s alkalmazsuk
// A sk kt pontjtl megadott tvolsgra lev pontjai: let public KtPonttlMegadottTvolsgra(Pont1: Kvaterni, Sk: Plane, tv1: double, tv2: double ): (Kvaterni * Kvaterni)= if Math.Abs( Kvaterni.dotProd4( Pont1, Sk.HomogeneousPlane )) > PICINY then ( Kvaterni( NULLA, Sk.NormVect), Kvaterni( NULLA, Sk.NormVect.Scal( MINEGY )))

else let tv = (Sk.Point.Vect - Pont1.Vect).abs let x = tv / KETT ( tv2 - tv1 ) * ( tv2 + tv1 ) / ( KETT * tv ) let y = Math.Sqrt( tv1 * tv1 - x * x ) let prhuzamosIrny = (Sk.Point.Vect - Pont1.Vect).Unit let merlegesIrny = prhuzamosIrny * Sk.NormVect

56

Kvaternik s alkalmazsuk
( Kvaterni( EGY, Pont1.Vect + prhuzamosIrny.Scal(x) + merlegesIrny.Scal(y) ), Kvaterni( EGY, Pont1.Vect + prhuzamosIrny.Scal(x) - merlegesIrny.Scal(y) ) ) // Kvaternival megadott pontok kzppontos tkrzse: let public KzppontosTkrzs( kzpPont: Kvaterni, Pont: Kvaterni ) : Kvaterni = Kvaterni( EGY, kzpPont.Vect.Scal( KETT ) - Pont.Vect )

Trbeli alakzatok lersa homogn koordintkkal


Elrebocstjuk, hogy az egyenesek kezelsben okozza a legkisebb vltozst a homogn koordintk alkalmazsa. Az egyenesnek van egy (homogn koordintit tartalmaz kvaternival lert) rgztett pontja, tovbb van irnyvektora. Az egyenes vltoz pontja homogn koordints kvaternijnak a vals rsze a rgztett pont vals rsze (az itt hasznlt homogn koordintk szerint 1), kpzetes rsze pedig a rgztett pont vektor sszetevjnek s az irnyvektor valahnyszorosnak sszege. (Az gy lert egyenes a Line objektum egy pldnya lehet.) A pontok kznsges, illetve idelis pontok lehetnek. A pontok homogn koordintit tartalmaz kvaterni vals rsze eszerint 1 vagy 0 (pontkvaterni). A skok homogn koordints krnyezetbeli lersra olyan kvaternit (skkvaternit) hasznlunk, amelynek a vektor sszetevje egysgvektor, vals rsze pedig negatv szm. Egyedl sknl merl fel az a krds, hogy mi a kapcsolat a Plane objektumpldny s ezt a skot ler skkvaterni kztt? Ugyanis a skot gy is gy is brzolhatjuk. A kt brzolsi forma kztt biztostottuk az tjrst: mindig azt a formt alkalmazhatjuk, amelyet ppen egyszerbbnek tartunk. A Plane objektumnak van HomogenouosPlane tulajdonsga, amely a skkvaternijt adja vissza, msrszt van olyan Plane konstruktor, amelynek egyetlen skkvaterni a paramtere. Ezrt az elz fejezetben bemutatott fggvnykszletben is tbb fggvnynek elksztettk az egyik sk-brzolsi formra s a msik skbrzolsi formra alkalmazott vltozatt is. Pldul: SkokMetszsvonala( Sk1: Plane, Sk2: Plane ) : Line HomognSkokMetszsvonala( Sk1: Kvaterni, Sk2: Kvaterni ) : Line Msfell, mkdik az albbi programrszlet is (Plane objektumbl skkvaterniv alakts): let Pont = Kvaterni( EGY, T, T, T ) let Sk = Plane( HROM, NGY, EGY ) let homognSk = Sk.HomogenouosPlane // Pont koordints megadsa // Sk a tengelypontjaibl // Ugyanaz kvaternival // Erre j

let tvolsg = Kvaterni.dotProd4( homognSk, Pont )

57

Kvaternik s alkalmazsuk
De visszafel is mkdik az talakts! Teht skkvaternijval lert skbl Plane skot hozunk ltre: let msikSk = Plane( homognSk ) // Kvaternibl Plane pldny

let skPontja = msikSk.Point // msikSk Plane pldny, van Point-ja A skkvaterni kpzetes rsze ppen a sk normlvektora, teht ugyanazt a vektort kapjuk msikSk.NormVect s homognSk.Vect hivatkozssal.

Hasonlkppen a Kvaterni_mveletek modulban elhelyezett brk mindegyikn lthatjk, hogy a felvett skok metszspontjt is meghatroztuk s rrajzoltuk az brra. Ott gy nz ki a kdrszlet: let kzsPont = Kvaterni.VectProd4( SkG.HomogeneousPlane, SkH.HomogeneousPlane, SkM.HomogeneousPlane ) A kvaterni alakban megadott skegyenletek ngydimenzs vektorszorzata kzvetlenl kiadja a metszspont kvaternit (a vals rsz mindjrt 1 rtk, mert a vektorilis szorzst vgz fggvny gy normlja az eredmnyt, ha a fggvny bemen paramterrtkei nem pontkvaternik). Teljes programot mutatunk, amely hrom pont homogn koordints kvaternijbl kiindulva hatrozza meg a pontokra illeszked skot. Egy negyedik, nem a skon lev pontnak pedig kiszmtja a sktl mrt tvolsgt. (A tvolsg eljeles, a sknak a Base0-t is tartalmaz trfelben negatv.) Felirat( "Homogn koordintk", 0, 500, 20, Color.DarkCyan ) HomognKoordintaHttr(Color.Silver) // A sk hrom pontja homogn (kvaterni-) koordintkkal: let P = Kvaterni( EGY, T, HROM, HROM ) PontRajz(Color.Lime, 2, P) KvaterniFelirat( "p", P, 0, -20, 20, Color.Lime ) KdFelirat( "p: Kvaterni( EGY, T, EGY, HROM )", 0, 650, 16, Color.Lime ) let Q = Kvaterni( EGY, MINEGY, T, EGY ) PontRajz( Color.Cyan, 2, Q ) KvaterniFelirat( "q", Q, -30, -15, 20, Color.Cyan ) KdFelirat( "q: Kvaterni (EGY, MINEGY, T, EGY )", 0, 680, 16, Color.Cyan ) let R = Kvaterni( EGY, NGY, -MSFL, FL ) PontRajz( Color.Magenta, 2, R ) KvaterniFelirat( "r", R, 0, -10, 20, Color.Magenta ) KdFelirat("r: Kvaterni(EGY, NGY, -MSFL, FL )", 0, 710, 16, Color.Magenta ) // Egy, a skra nem illeszked pont homogn koordintkkal: let T = Kvaterni( EGY, -HROM, -KETT, HROM ) PontRajz( Color.Tomato, 2, T ) KvaterniFelirat( "t", T, 0, -40, 20, Color.Tomato ) KdFelirat( "t: Kvaterni( EGY, -HROM, -KETT, HROM )", 0, 740, 16, Color.Tomato )

58

Kvaternik s alkalmazsuk

// A sk egyenletnek meghatrozsa (Kvaterni.VectProd4 hvsval): let S = Kvaterni.VectProd4( P, Q, R ) // Ellenrzs: illeszked pontnl Kvaterni.dotProd4(S,.) = 0 let prbaP = Kvaterni.dotProd4( S, P ) let prbaQ = Kvaterni.dotProd4( S, Q ) let prbaR = Kvaterni.dotProd4( S, R ) // A kpzetes tengelyeken tallhat sk-metszspontok meghatrozsa: let iTengelyen = -S.re / S.imI let jTengelyen = -S.re / S.imJ let kTengelyen = -S.re / S.imK // Ti = Kvaterni(1, iTengelyen, 0, 0) // Tj = Kvaterni(1, 0, jTengelyen, 0) // Tk = Kvaterni(1, 0, 0, kTengelyen)

// A Plane objektum Sk pldnynak konstrulsa: let Sk = Plane( iTengelyen, jTengelyen, kTengelyen )

59

Kvaternik s alkalmazsuk
SkRajz( Color.SteelBlue, Sk, 5.0 ) // A sk rajzoltatsa:

// A skra nem illeszked pont sktl val tvolsgnak meghatrozsa // a ngydimenzis skalris szorzat felhasznlsval: let tvolsg = Kvaterni.dotProd4( S, T ) // A sk tvolsgnak ellenrz meghatrozsa "jzan paraszti sszel": let dfsPont = SkotDfEgyenes( Sk, Line( T, Sk.NormVect ) ) let tv = ( T - dfsPont ).abs // A sk tvolsga a Base0 ponttl: let df = SkotDfEgyenes(Sk, Line(Base0, Sk.NormVect)) let sktv = (Base0 - df).abs // Kirsok a rajzfelletre... Az brn kirt eredmnyekbl is lthat, hogy az skkvaterninak a komplex vektora a sk normlvektora. A sknak a kpzetes tengelyekkel val metszspontjait a szemlltets rdekben egy, a skra simul hromszgsorozat megrajzolshoz szmtottuk ki. Ellenriztk is, hogy a sk egytthatkvaternijnak s egy, a skra nem illeszked pont kvaternijnak a ngydimenzis skalris szorzata abszolt rtke szerint a pont s a sk (eljeles) tvolsgt szolgltatja. A hrom (pontkvaternijval adott) pontra illeszked sk skkvaternijnak meghatrozsa, valamint a hrom (skkvaternijval adott) sk kzs pontja pontkvaternijnak meghatrozsa ugyanaz a matematikai problma (dualits ttele). Az albbi pldban hrom sk kzs pontjnak homogn koordintit szmoljuk VectProd4 -gyel. HomognKoordintaHttr( Color.Silver ) // Kiindulsul homogn koordintival megadunk t pontot: let let let let let P Q R T U = = = = = Kvaterni(EGY, Kvaterni(EGY, Kvaterni(EGY, Kvaterni(EGY, Kvaterni(EGY, T, EGY, HROM) MINEGY, T, NGY) NGY, -MSFL, FL) -HROM, -KETT, HROM) TIZENKETT, -HT, KETT)

// A skokat hrom-hrom fenti pontra illesztjk: let S1 = Kvaterni.VectProd4(P, Q, R) let S2 = Kvaterni.VectProd4(T, Q, R) let S3 = Kvaterni.VectProd4(P, U, R)

60

Kvaternik s alkalmazsuk

let H1 = Triangle(P, Q, R) // Lthatv tesszk a skokat: Hromszg(Pens.SteelBlue, H1, 2.0) let H2 = Triangle(T, Q, R) Hromszg(Pens.Lime, H2, 1.2) let H3 = Triangle(P, U, R) Hromszg(Pens.Orange, H3, 1.8) // Meghatrozzuk a hrom sk metszsponti homogn koordintit: let mutable Pont = Kvaterni.VectProd4(S1, S2, S3) A hrom skot gy vettk fel, hogy skok metszspontjnak koordinti kzs pontjuk legyen. Ezrt ellenrizni tudjuk az eredmnyt: a koordintival megegyeznek.

61

Kvaternik s alkalmazsuk
A sk homogn koordints egyenletnek szerkezett foglaljuk ssze. A skkvaterni kpzetes rsze a sk normlisa. (A ngydimenzis skalris szorzsnl a kpzetes rsznek s a pontok hromdimenzis trbeli helyvektornak a skalris szorzata ugyanazt az rtket adja a skot kifeszt pontok esetn: a koordintarendszer kezdpontjnak, amely hol az origo, hol a Base0 pont s a sk Near pontjnak a tvolsgt. Persze, mert ez a skalrszorzat mindig a skon tallhat pont helyvektornak vetlete a normlis irnyra.) A Kvaterni_mveletek modulban ugyanis a sk egyenletnek hrom pontja kvaternijbl val meghatrozsnl ( #Ngydimenzis_vektorilis_szorzat ) a kapott kvaterni kpzetes rsznek abszolt rtkvel el is osztottuk a kvaternit, gy elrtk, hogy a kpzetes rsz a sk normlis egysgvektora. A sk egytthatit tartalmaz kvaternit mg gy alaktjuk ott a ltrehozsnl, hogy vals rsze negatv legyen. (Mivel a sk egytthati csak az arnyossg erejig meghatrozottak, tetszleges llandval szorozhatjuk, oszthatjuk valamennyi egytthatt, a sk nem vltozik.) Ha a sk kvaternijnak vals rsze negatv, akkor a pontok sktl mrt tvolsgnak eljelszablya a kvetkez: a sk kvaternijnak s egy, a skra nem illeszked homogn koordintj pont kvaternijnak ngydimenzis skalris szorzata a pont sktl mrt tvolsgt gy eljelezi, hogy a tvolsg a Base0 pontot tartalmaz trflben negatv, a sk ltal kijellt msik trflben pozitv. A Base0 pont tvolsga a sktl a sk kvaternijnak vals rsze, hiszen Base0 = Kvaterni(1, 0, 0, 0).

Egy kls pont tvolsga a sktl a pont Base0-bl indul hromdimenzis helyvektora s a normlis irny egysgvektor skalris szorzatbl ( ), valamint a Base0 pont sktl mrt ( DV ) tvolsgbl ll. Mivel a pont vals rsze 1, ez ppen a ngydimenzis skalris szorzat.

62

Kvaternik s alkalmazsuk Kvaternik programozott megjelentse ( F# )


Ebben a fejezetben a kpernyn val megjelentshez szksges tbb fggvnyt ismertetnk. A fejezet tanulmnyozst nyugodtan kihagyhatja az, akit nem rdekelnek a programozsi rszletek. Msrszt szeretnm megmutatni, hogy milyen egyszer a programozs, hogy mennyire knny pldul a koordintatengelyek helyzetn vltoztatni az albbi szerkezetekkel. let private tr4Ox : int let private tr4Oy : int let private tr4Oz : int = 450 = 600 = 0 // Az orig helye az 1000 x 1000 // kppontnyi rajzterleten bell // Mlysgi koordinta (lthatsg) // A vals tengelyvg koordinti

let private tr4Rx : int = 820 let private tr4Ry : int = 780 let private tr4Rz : int = +100 let private tr4Ix : int = 830 let private tr4Iy : int = 450 let private tr4Iz : int = +100 let private tr4Jx : int = 650 let private tr4Jy : int = 320 let private tr4Jz : int = -200 let private tr4Kx : int = 250 let private tr4Ky : int = 220 let private tr4Kz : int = +100 let private SKLA = double 6.0 // // // // //

// Az i kpzetes tengely vgpontjnak // elhelyezse a kpen ... // A j kpzetes tengely vgpontjnak // elhelyezse a kpen ... // A k kpzetes tengely vgpontjnak // elhelyezse a kpen ... // Vgpont az egysg hnyszorosa

Ez a fggvny a kvaterni koordintbl kp koordintt szmol. A kpi koordinta egy hrmas (tuple), amelyben a vzszintes s a fggleges kpi koordinta mellett mindig egy mlysgi koordintt is kapunk. A mlysgi koordintnak csak a lthatsg eldntsekor van szerepe (mskor ltalban ezt a koordintt eldobjuk).

let KvaterniPont( fKvaterni : Kvaterni ) : ( int * int * int ) = (tr4Ox + int((fKvaterni.re * double(tr4Rx - tr4Ox) + fKvaterni.imI * double(tr4Ix - tr4Ox) + fKvaterni.imJ * double(tr4Jx - tr4Ox) + fKvaterni.imK * double(tr4Kx - tr4Ox)) / SKLA), tr4Oy + int((fKvaterni.re * double(tr4Ry - tr4Oy) + fKvaterni.imI * double(tr4Iy - tr4Oy) + fKvaterni.imJ * double(tr4Jy - tr4Oy) + fKvaterni.imK * double(tr4Ky - tr4Oy)) / SKLA), tr4Oz + int((fKvaterni.re * double(tr4Rz - tr4Oz) + fKvaterni.imI * double(tr4Iz - tr4Oz) + fKvaterni.imJ * double(tr4Jz - tr4Oz) + fKvaterni.imK * double(tr4Kz - tr4Oz)) / SKLA))

63

Kvaternik s alkalmazsuk
// // // // A kvaterni koordintkbl preczen szmoltuk ki az elz fggvnyben a kpi koordintkat. Meghagytunk mg valamifle mlysgi koordintt is, amely viszont lehetsget nyjt arra, hogy trbeli brnk vetlett kiss talaktsuk, perspektivikuss tegyk. A fggvnyt mdostjuk:

let KvaterniPont(fKvaterni : Kvaterni) : (int * int * int ) = let deltaZ = (fKvaterni.re * double(tr4Rz - tr4Oz) + fKvaterni.imI * double(tr4Iz - tr4Oz) + fKvaterni.imJ * double(tr4Jz - tr4Oz) + fKvaterni.imK * double(tr4Kz - tr4Oz)) / SKLA let deltaX = (fKvaterni.re * double(tr4Rx - tr4Ox) + fKvaterni.imI * double(tr4Ix - tr4Ox) + fKvaterni.imJ * double(tr4Jx - tr4Ox) + fKvaterni.imK * double(tr4Kx - tr4Ox)) / SKLA * 2800.0 / (3000.0 - deltaZ) let deltaY = (fKvaterni.re * double(tr4Ry - tr4Oy) + fKvaterni.imI * double(tr4Iy - tr4Oy) + fKvaterni.imJ * double(tr4Jy - tr4Oy) + fKvaterni.imK * double(tr4Ky - tr4Oy)) / SKLA * 2800.0 / (3000.0 - deltaZ) (tr4Ox + int(deltaX), tr4Oy + int(deltaY), tr4Oz + int(deltaZ)) // Az brn piros sznnel a kocka perspektv vettses vltozatt ltjk:

A kockkat sszehasonltva lthatjuk, hogy a szablyos-nak szerkesztett fekete kockhoz kpest szablyosabbnak ltjuk a perspektivikusan torztott piros vltozatot.

64

Kvaternik s alkalmazsuk
A perspektv vettsnl egyenl hosszsg szakaszok kzl a tvolabbiak megrvidlnek, ezrt a drtvzas kocka kpt az albbi bra vettskjn lthathoz hasonlnak tapasztaljuk:

A perspektv vetts szmtsnak menete a kvetkez bra alapjn lthat be:

A programban tv = 2800, bzis = 3000. z mlysgi koordinta a -200 - +200 hatrok kztti rtk. Az O jel pontba kpzelve a szemnket, a tle tvolsgra lev skon a trgy A, B, C, D pontjainak kpt A, B, C, D-nek ltnnk. A skon az x s y koordinta egyarnt a kplet szerint mdosul.

65

Kvaternik s alkalmazsuk
// Trttvonalakat a kpen Point-ok sorozataknt adunk meg. Segtsg // ebben ez a fggvny, amely a kvaterni koordintkbl (a mlysgi // koordinta eldobsval) rgtn Point-ot ad vissza: let KvaterniKpen( fKvaterni : Kvaterni ) : Point = let mutable lKpPont : Point = new Point(0,0) let ( tmenX, tmenY, tmenZ ) = KvaterniPont( fKvaterni ) lKpPont.X <- tmenX lKpPont.Y <- tmenY lKpPont // A kvaternik vektor komponenseknt lert trben kt pont egyenes // vonallal val sszektst vgzi: let sszekt( fToll : Pen, fEzt : Kvaterni, fEzzel : Kvaterni ) = let ( lEztX, lEztY, lEztZ ) = KvaterniPont( fEzt ) let ( lEzzelX, lEzzelY, lEzzelZ ) = KvaterniPont( fEzzel ) bra.DrawLine( fToll, lEztX, lEztY, lEzzelX, lEzzelY ) // Kpi koordintival megadott pontban a pontot kijell kis // keresztet rajzol: let Kereszt( fSzn : Color, fVastag : int, fX : int, fY : int ) = bra.DrawLine( new Pen(fSzn, float32 fVastag), fX - VON, fY - VON, fX + VON, fY + VON ) bra.DrawLine( new Pen(fSzn, float32 fVastag), fX - VON, fY + VON, fX + VON, fY VON ) // Kvaternival megadott pontot a rajzon kereszttel megjell: let PontRajz( fSzn : Color, fVastag : int, Pont : Kvaterni ) = let ( pontX, pontY, pontZ ) = KvaterniPont( Pont ) Kereszt( fSzn, fVastag, pontX, pontY ) // Kvaternival kijellt pontok kztt nyl vgzds vektort rajzol: let VektorRajz ( fSzn : Color, fVastag : int, fVg : Kvaterni, fHegy :Kvaterni ) = let lToll : Pen = new Pen( fSzn, float32 fVastag ) let ( lVgX, lVgY, lVgZ ) = KvaterniPont( fVg ) let ( lHegyX, lHegyY, lHegyZ ) = KvaterniPont( fHegy ) let lSzt : double = 10.0 let lCscs : double = 20.0 bra.DrawLine( lToll, lHegyX, lHegyY, lVgX, lVgY) let lTg = double(lVgY - lHegyY) / double(lVgX - lHegyX) let lSzg : double = Math.Atan(lTg) * VBLFOK let lXCscs = if lVgX < lHegyX then -lCscs else lCscs

66

Kvaternik s alkalmazsuk
let mutable lYCscs = if lVgY < lHegyY then if lSzg < NULLA then lYCscs <- -lYCscs bra.DrawLine( lToll, lHegyX, lHegyY, lHegyX + int(lXCscs * Math.Cos((lSzg + lHegyY + int(lYCscs * Math.Sin((lSzg + bra.DrawLine( lToll, lHegyX, lHegyY, lHegyX + int(lXCscs * Math.Cos((lSzg lHegyY + int(lYCscs * Math.Sin((lSzg -lCscs else lCscs

lSzt) * FOKBLV)), lSzt) * FOKBLV)) ) lSzt) * FOKBLV)), lSzt) * FOKBLV)) )

// Line osztly pldnyaknt megadott egyenest a rajzon vonallal s // vonal irny egysgvektorral kijell: let EgyenesRajz ( fEgyenesSzn : Color, fEgyenes : Line, fSzakaszMret : Double ) = let Egyik : Kvaterni = fEgyenes.Point1 let Msik : Kvaterni = fEgyenes.Point2 let irnyVektorRajz : Vector = fEgyenes.Vect sszekt( new Pen(fEgyenesSzn, float32 1.0), Egyik - (Msik - Egyik).Scal(fSzakaszMret), Msik + (Msik - Egyik).Scal(fSzakaszMret) ) PontRajz( fEgyenesSzn, 2, Egyik ) PontRajz( fEgyenesSzn, 2, Msik ) VektorRajz( fEgyenesSzn, 3, Egyik, Egyik + Kvaterni(NULLA, irnyVektorRajz) )

Hasb forgatsa (Visual Basic program)


Ebben a fejezetben olyan programrszletet mutatunk be, amellyel az skon elhelyezked alap, a irnyban feltornyosul hasbot forgatunk ( tengely krl 90-kal). A forgatst elvgz ltalnosForgats nev szubrutin bemen paramterei kztt nem csak a trbeliPontok kvaternitmb szerepel, hanem megadhat a forgats tengelye s szge is. ' A kocka 8 sarokpontjhoz tartoz kvaterni: Dim ngyzetalapHasb() As Kvaterni_mveletek.Kvaterni = { New New New New New New New New Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, 0.0, 0.0, 3.5, 3.5, 0.0, 0.0, 3.5, 3.5, 0.0, 3.5, 3.5, 0.0, 0.0, 3.5, 3.5, 0.0, 0.0), 0.0), 0.0), 0.0), 3.5), 3.5), 3.5), 3.5) }

67

Kvaternik s alkalmazsuk
Dim toll1 = New Pen(Color.Red, 3) Dim toll2 = New Pen(Color.Lime, 2) ltalnosForgats( ngyzetalapHasb, New Vector(NULLA, NULLA, EGY), Math.PI / KETT, toll1, toll2 )

' A hatszg alap hasb 12 sarokpontjhoz tartoz kvaterni: Dim hatszgalapHasb() As Kvaterni_mveletek.Kvaterni = { New New New New New New New New New New New New Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, Kvaterni_mveletek.Kvaterni(1.0, 0.0, 3.045, 0.0), 1.75, 0.0, 0.0), 5.25, 0.0, 0.0), 7.0, 3.045, 0.0), 5.25, 6.09, 0.0), 1.75, 6.09, 0.0), 0.0, 3.045, 3.5), 1.75, 0.0, 3.5), 5.25, 0.0, 3.5), 7.0, 3.045, 3.5), 5.25, 6.09, 3.5), 1.75, 6.09, 3.5) }

68

Kvaternik s alkalmazsuk

' Egy, a sarokponti kvaterniival adott hasbot a tollal kirajzoltat: Sub HasbRajz( ByVal fToll As Pen, ByVal sarokPontok() As Kvaterni_mveletek.Kvaterni) Dim lI, lJ, lK, lM As Integer Dim rajzPontok(UBound(sarokPontok)) _ As Tuple(Of Integer, Integer, Integer) For lI = LBound(sarokPontok) To UBound(sarokPontok) rajzPontok(lI) = KvaterniPont(sarokPontok(lI)) Next lI

69

Kvaternik s alkalmazsuk
For lI = LBound(rajzPontok) To (UBound(rajzPontok) - 1) \ 2 lJ = lI + 1 If lJ > (UBound(rajzPontok) - 1) \ 2 Then lJ = 0 End If sszekt(fToll, rajzPontok(lI), rajzPontok(lJ)) lK = (UBound(rajzPontok) - 1) \ 2 + lI + 1 lM = lK + 1 If lM > UBound(rajzPontok) Then lM = (UBound(rajzPontok) - 1) \ 2 + 1 End If sszekt(fToll, rajzPontok(lK), rajzPontok(lM)) sszekt(fToll, rajzPontok(lI), rajzPontok(lK)) Next lI End Sub ' ' ' ' A sarokponti kvaterniival adott hasbot eredeti helyzetben az s tollal kirajzoltatja, majd az sszetevivel megadott vektor egysgvektora krl az tadott szggel elforgatja. Az elforgatott hasbot az tadott j tollal rajzoltatja a kpernyre.

Sub ltalnosForgats( _ ByVal fPontok() As Kvaterni_mveletek.Kvaterni, ByVal tengelyIrny As Kvaterni_mveletek.Vector, ByVal fSzg As Double, ByVal fsToll As Pen, ByVal fjToll As Pen) Dim lSzg As Double = fSzg / KETT Dim lQ As Kvaterni_mveletek.Kvaterni = _ New Kvaterni_mveletek.Kvaterni( _ Math.Cos(lSzg), tengelyIrny.Unit.Scal(Math.Sin(lSzg))) Dim lQKonj As Kvaterni_mveletek.Kvaterni = lQ.Konj Dim jPontok(UBound(fPontok)) As Kvaterni_mveletek.Kvaterni HasbRajz(fsToll, fPontok) For lI = LBound(fPontok) To UBound(fPontok) jPontok(lI) = lQ * fPontok(lI) * lQKonj Next lI HasbRajz(fjToll, jPontok) End Sub

' Forgats

70

Kvaternik s alkalmazsuk
' A hasb brja eltt az annak megrajzolshoz szksges eljrs' hvst lthattk. Itt a hatszg alap hasb j krli 180 fokos ' elforgatst vgz eljrs-hvst ismertetjk. ' Az eljrs paramtere a sarokpontokat ler kvaterni-tmb, a ' forgats tengelynek mint vektornak az sszetevi, a forgats szge, ' valamint a rajzoltatshoz hasznlt tollak. ltalnosForgats(hatszgalapHasb, New Vector(NULLA, EGY, NULLA), Math.PI, toll1, toll2) Ltvnyos brkhoz juthatunk a KrbeForgats szubrutin hasznlatval. Paramterknt lehet megadni az indul rajz sznt, valamint azt is, hogy hny lpsben trtnjk meg a krbeforgats. ( Csak 100-nl kisebb lpsszm esetn vltogatja a szneket) Sub KrbeForgats( _ ByVal trbeliPontok() As Kvaterni_mveletek.Kvaterni, ByVal tengelyIrny As Kvaterni_mveletek.Vector, ByVal fLps As Integer, ByVal fsToll As Pen ) Dim lByte As New Random Dim lSzn As Color, ljToll As Pen = fsToll Dim lSzg As Double = Math.PI / fLps Dim lQ As Kvaterni_mveletek.Kvaterni = _ New Kvaterni_mveletek.Kvaterni(Math.Cos(lSzg), _ tengelyIrny.Unit.Scal(Math.Sin(lSzg))) Dim lQKonj As Kvaterni_mveletek.Kvaterni = lQ.Konj HasbRajz(fsToll, trbeliPontok) For lN = 1 To fLps If fLps < 100 Then lSzn = Color.FromArgb( _ lByte.Next(256), lByte.Next(256), lByte.Next(256)) ljToll = New Pen(lSzn, 2) End If For lI = LBound(trbeliPontok) To UBound(trbeliPontok) trbeliPontok(lI) = lQ * trbeliPontok(lI) * lQKonj Next lI If lN = fLps Then HasbRajz(New Pen(Color.Red, 2), trbeliPontok) Else HasbRajz(ljToll, trbeliPontok) End If Next lN End Sub

71

Kvaternik s alkalmazsuk
A sznek vletlen megvlasztsval, a tengely krl 5 lpsben krbeforgatva:

KrbeForgats( hatszgalapHasb, New Vector(EGY, NULLA, NULLA), 5, Pens.Red) De egszen ms kpet kapunk, ha 100 lpsben vgezzk el a krbeforgatst a tengely krl: KrbeForgats( hatszgalapHasb, New Vector(EGY, NULLA, NULLA), 100, Pens.Lime)

72

Kvaternik s alkalmazsuk

73

Kvaternik s alkalmazsuk Skidom forgatsa (Visual Basic program)


Hasonlan ltvnyos eredmnyhez juthatunk, ha az skban szerkesztett skidomot forgatjuk meg az illetve a tengely krl gy, hogy teljes krbeforgatst vgezznk el. A LapForgats nev szubrutin a paramterknt tadott pontokkal lert skidommal ppen ezt vgzi. Els paramtervel azt tudjuk belltani, hogy a forgatst az vagy a tengely krl hajtsa- e vgre.. Dim keresztPontok() As Kvaterni_mveletek.Kvaterni = {New Kvaterni_mveletek.Kvaterni(1.0, 1.0, 3.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 3.0, 3.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 3.0, 1.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 4.0, 1.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 4.0, 3.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 6.0, 3.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 6.0, 4.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 4.0, 4.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 4.0, 6.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 3.0, 6.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 3.0, 4.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 1.0, 4.0, 0.0), New Kvaterni_mveletek.Kvaterni(1.0, 1.0, 3.0, 0.0)} Sub SkbeliRajz( ByVal fToll As Pen, ByVal skPontok() As Kvaterni_mveletek.Kvaterni) Dim lI, lJ As Integer Dim rajzPontok(UBound(skPontok)) _ As Tuple(Of Integer, Integer, Integer) For lI = LBound(rajzPontok) To UBound(rajzPontok) rajzPontok(lI) = KvaterniPont(skPontok(lI)) Next lI For lI = LBound(rajzPontok) To UBound(rajzPontok) lJ = lI + 1 If lJ > UBound(rajzPontok) Then lJ = 0 End If sszekt(fToll, rajzPontok(lI), rajzPontok(lJ)) Next lI End Sub Sub LapForgats( ByVal skbeliPontok() As Kvaterni_mveletek.Kvaterni, ByVal fIKrl As Boolean, ByVal fLps As Integer, ByVal fsToll As Pen, ByVal fjToll As Pen) Dim lI As Integer Dim lSzg As Double = Math.PI / fLps Dim lCos As Double = Math.Cos(lSzg) Dim lSin As Double = Math.Sin(lSzg) Dim lQ As Kvaterni_mveletek.Kvaterni

74

Kvaternik s alkalmazsuk
Dim lQKonj As Kvaterni_mveletek.Kvaterni If fIKrl Then lQ = New Kvaterni_mveletek.Kvaterni( _ lCos, lSin, NULLA, NULLA) Else lQ = New Kvaterni_mveletek.Kvaterni( _ lCos, NULLA, lSin, NULLA) End If lQKonj = lQ.Konj SkbeliRajz(fsToll, skbeliPontok) For lN = 1 To fLps - 1 For lI = LBound(skbeliPontok) To UBound(skbeliPontok) skbeliPontok(lI) = lQ * skbeliPontok(lI) * lQKonj Next lI SkbeliRajz(fjToll, skbeliPontok) Next lN End Sub LapForgats(keresztPontok, True, 150, Pens.Red, Pens.DarkBlue)

75

Kvaternik s alkalmazsuk

Vgl kr pontjait az egyenletbl ellltva kt rajzot ksztnk. nmaga krl forgatjuk a krt, gy gmbt, majd kls tengely krl forgatjuk a krlapot, gy truszt rajzoltatunk: Dim ellipszisPontok(239) As Kvaterni_mveletek.Kvaterni For lI = 0 To 239 If lI < 60 Then ellipszisPontok(lI) = New Kvaterni_mveletek.Kvaterni( 1.0, HATVANAD * lI - EGY + T, Math.Sqrt(EGY * EGY (HATVANAD * lI - EGY) * (HATVANAD * lI - EGY)) + T, ElseIf lI < 120 Then ellipszisPontok(lI) = New Kvaterni_mveletek.Kvaterni( 1.0, HATVANAD * lI - EGY + T, Math.Sqrt(EGY * EGY (HATVANAD * lI - EGY) * (HATVANAD * lI - EGY)) + T,

_ _ 0.0) _ _ 0.0)

76

Kvaternik s alkalmazsuk
ElseIf lI < 180 Then ellipszisPontok(lI) = New Kvaterni_mveletek.Kvaterni( _ 1.0, HATVANAD * (239 - lI) - EGY + T, _ - Math.Sqrt(EGY * EGY - (HATVANAD * (239 - lI) - EGY) _ * (HATVANAD * (239 - lI) - EGY)) + T, 0.0) Else ellipszisPontok(lI) = New Kvaterni_mveletek.Kvaterni( _ 1.0, HATVANAD * (239 - lI) - EGY + T, _ - Math.Sqrt(EGY * EGY - (HATVANAD * (239 - lI) - EGY) _ * (HATVANAD * (239 - lI) - EGY)) + T, 0.0) End If Next lI LapForgats(ellipszisPontok, False, 200, Pens.Red, Pens.Lime)

77

Kvaternik s alkalmazsuk Segdmennyisgek a szablyos testek rajzolshoz


A szablyos testeket (tetrader, oktader, hexader, dodekader, ikozader) a kvaternik kpzetes rsze ltal lert hromdimenzis trben szerkesztjk meg. Az a mdszernk, hogy a szablyos testek oldalhosszsgbl ( amelyet -val jellnk ) kiindulva szmtssal hatrozzuk meg a szablyos test tbbi, a test szerkesztshez szksges szakasznak mrett. Pldul az albbi bra jellseit hasznlva a szablyos tszgn vgznk szmtsokat, hogy a dodekader, illetve az ikozader szerkesztsnl szksgess vl szakaszhosszakat kiszmtsuk.

A szablyos tszg valamennyi tlja ugyanakkora, ezt jelltk c-vel. Az brn a zld s piros sznnel festett kt hromszg egybevg, hiszen mindkettnek mindegyik hegyesszge 36-os (a szablyos tszg krbe rhat, s megegyez mret hrokhoz megegyez mret kerleti szgek tartoznak), tovbb az alapjuk kzs, ezrt . A kis piros hromszg s a nagy piros hromszg, egymshoz hasonl, hiszen a szgeik megegyeznek. Ebbl a hasonlsgbl kvetkezik, hogy ( ) Az arnyprt (aranymetszs) talaktva lthatjuk, hogy .

78

Kvaternik s alkalmazsuk
A msodfok egyenlet megold kplett alkalmazva (s csak a pozitv gykt megtartva): ( )

A szablyos tszg b-vel jellt (srgra sznezett) magassgt is szmthatjuk: ( Ebbl ( ( ) ) )

A szablyos tszg krlrt krnek kzppontja a cscsoktl egyenl ( ) tvolsgra van. Ezt is meghatrozhatjuk ismeretben az elz oldali bra alapjn: ( ) ( ) ( ) : ( ) ( )

De a lap tetejn lev kplet szerint a jobb oldal ppen ( )

(Csak megjegyzem, hogy az interneten a kvetkez kpletre bukkantam:

A kt kplet azonossga bizonythat, teht ugyanazt az eredmnyt szolgltatja mindkett.) A tetrader rajzolst gy kezdtk, hogy felvettnk egy skot, amelyik mind a hrom tengelyt metszi, s egy egyenest, amelyik nem prhuzamos a skkal. A dfspontot a sk normlisa krl ktszer 120kal elforgatva egyenl oldal hromszget kaptunk, amely a tetrader alapjul szolglt. (A forgatsi tengely a sk normlisa, amely a sk orighoz legkzelebbi pontjn megy keresztl.) Az alap slyponti (a cscstl a magassg ktharmadnl lev) vektorhoz az alapra merleges (a sk normlisa irnyba mutat) p hosszsg vektort hozzadva jelltk ki a tetrader negyedik cscspontjt. ( )

Dodekader ksztsnl az alap tszghz illeszked tovbbi szablyos tszgek szerkesztst a kvetkez bra alapjn elvgzett szmtsokkal alapoztuk meg. A rajzon az elz oldalakon bevezetett betjelkkel hivatkoztunk a korbbiakban kiszmolt mennyisgekre.

79

Kvaternik s alkalmazsuk

Az brn lthat n a c oldal szablyos hromszg magassga:

Az 5T1 hromszg skja a 0. s 2. cscspont kztti szakasz felezpontjn keresztl a szakaszra merleges sk. Ebben a skban a T ponttl a fent meghatrozott n, az 1. cscstl pedig a tvolsgra lev 5. pontot kell meghatrozni. A Kvaternis_szmtsok modul KtPonttlMegadottTvolsgra nev eljrsval llthatjuk el ezt a pontot. Ugyangy kaptuk meg, persze, az U ponttl n, a 0. ponttl a tvolsgra lev 9. pont helyt is. A 0., 1., 5., 9. pont skjban szintn a fenti eljrssal lehet az 5. s a 9. ponttl is a tvolsgra lev 14. pontot kijellni.

80

Kvaternik s alkalmazsuk

Ikozadernl is egy szablyos tszgbl indulunk ki. A szablyos tszg kzppontjt meghatrozzuk, majd ott a szablyos tszg normlvektora irnyba mutat, q hosszsg vektort adunk hozz a pont helyvektorhoz, gy lltjuk el az tszg fltti cscspontot. Az tszg alap gla magassgt egy olyan derkszg hromszgbl szmtjuk, amelynek tfogja az a oldal, a szablyos test oldalhossza, egyik befogja pedig az a -oldal sokszg krlrt krnek sugara ( r ). ( )

A 4. cscsnl trkiz (cyan) sznnel berajzolt derkszg hromszg alapja a szablyos tszg rajza ( ) alapjn ppen Ugyanennek a hromszgnek az tfogja ppen az oldal egyenl oldal hromszg magassga, befogja pedig az ikozaderben egymssal prhuzamosan (br a sajt lapjn bell egymshoz kpest kzppontosan tkrztten elhelyezked) kt szablyos tszg tvolsga. ( ) ( ) ( )

81

Kvaternik s alkalmazsuk

Ezeknek a kpleteknek az ismeretben az egyes szablyos testek szerkesztsnek kdjt, a megszerkesztett drtvz-brt s a zrt fellet szablyos testek kpt lthatjk a kvetkez fejezet utni oldalakon. (Msik lapon az eredeti test mellett annak egy elforgatottjt is mutatjuk.)

Programozsi szerkezetek a szablyos testekhez ( F# )


A szablyos testek konvexek, leik egyforma hosszsgak, lapjaik egybevg, szablyos skidomok: hromszgek, ngyzetek vagy tszgek. Az albbi tblzatban sszefoglaljuk az adataikat: Megnevezs Cscsok szma: lek szma: Lapok szma: Skidom: Tetrader 4 6 4 hromszg Oktader 6 12 8 hromszg Hexader 8 12 6 ngyzet Dodekader 20 30 12 tszg Ikozader 12 30 20 hromszg

( Euler ttele: cscsok szma + lapok szma = lek szma 2. ) A programban a cscsok helyt kvaternikkal hatrozzuk meg. (Ezeknek a kvaterniknak a vals rsze 0, a kpzetes rsz rja le a hromdimenzis teret). A cscsok sorszmnak megvlasztsa termszetesen nknyes, de az lek s lapok cscs-sorszmokkal val megadshoz clszer a sorszmozs menett rgzteni. Az albbi adatstruktrk tallhatk a program kdjban: // A tetrader (szmtand) cscspontjai: let tPontok : Kvaterni array = [| O; O; O; O|] // 0, 1, 2 az alap szablyos hromszg sorszmozsa, 3 az alapon // kvl lev cscs sorszma. Ezzel a szmozssal az lek: let tetraderlek : (int * int) array = [| (0, 1); (1, 2); (2, 0); (0, 3); (1, 3); (2, 3) |] // A lapok leri tsk, most csak hrom rtk kihasznlt. Mindegyik // nem kihasznlt helyre -1 kerl: let tetraderLapok : (int * int * int * int * int) array = [| (0, 1, 2, -1, -1); (0, 1, 3, -1, -1); (1, 2, 3, -1, -1); (2, 0, 3, -1, -1) |]

82

Kvaternik s alkalmazsuk
// Az oktader cscspontjait trol tmb: let oPontok : Kvaterni array = [| O; O; O; O; O; O|] // Az oktader lei (0, 1, 2, 3 sorszm a kiindul ngyzethez...): let oktaderlek : (int * int) array = [| (0, 1); (1, 2); (2, 3); (3, 0); (0, 4); (1, 4); (2, 4); (3, 4); (0, 5); (1, 5); (2, 5); (3, 5) |] // Az oktader lapjai (a -1 rtkek helykitltk...): let oktaderLapok : (int * int * int * int * int) array = [| (0, 1, 4, -1, -1); (1, 2, 4, -1, -1); (2, 3, 4, (3, 0, 4, -1, -1); (0, 1, 5, -1, -1); (1, 2, 5, (2, 3, 5, -1, -1); (3, 0, 5, -1, -1) |] // A hexader (kocka) cscsponjainak trolsra szolgl tmb: let hPontok : Kvaterni array = [| O; O; O; O; O; O; O; O |] // A kocka lei: let hexaderlek : (int * int) array = [| (0, 1); (1, 2); (2, 3); (3, 0); (4, 5); (5, 6); (6, 7); (7, 4); (0, 4); (1, 5); (2, 6); (3, 7) |] // A kocka lapjai (a -1-ek helykitltk...): let hexaderLapok : (int * int * int * int * int) array = [| (0, 1, 2, 3, -1); (4, 5, 6, 7, -1); (0, 1, 5, 4, -1); (1, 2, 6, 5, -1); (2, 3, 7, 6, -1); (3, 0, 4, 7, -1) |] // A dodekader cscspontjait ez a tmb vrja: let dPontok : Kvaterni array = [| O; O; O; O; O; O; O; O; O; O; O; O; O; O; O; O; O; O; O; O |] // A dodekader lei (0, 1, 2, 3, 4, illetve 5, 6, 7, 8, 9 a kt // kiindulsi szablyos tszg cscs-sorszma): let dodekaderlek : (int * int) array = [| (0, 1); (1, 2); (2, 3); (3, 4); (4, 0); (1, 5); (2, 6); (3, 7); (4, 8); (0, 9); (5, 10); (6, 10); (6, 11); (7,11); (7, 12); (8, 12); (8, 13); (9, 13); (9,14); (5,14); (15, 16); (16, 17); (17, 18); (18, 19); (19, 15); (11,15); (12, 16); (13, 17); (14, 18); (10, 19) |] // A dodekader lapjai:

-1, -1,

-1); -1);

83

Kvaternik s alkalmazsuk
let dodekaderLapok : (int * int * int * int * int) array = [| (0, 1, 2, 3, 4); (4, 8, 13, 9, 0); (3, 7, 12, 8, 4); (1, 2, 6, 10, 5); (0, 1, 5, 14, 9); (14, 18, 19, 10, 5); (3, 2, 6, 11, 7); (6, 10, 19, 15, 11); (11, 15, 16, 12, 7); (13, 17, 18, 14, 9); (17, 13, 8, 12, 16); (15, 16, 17, 18, 19) |] // Az ikozadernek mindssze 12 cscsa van, ide kerlnek: let iPontok : Kvaterni array = [| O; O; O; O; O; O; O; O; O; O; O; O |] // Az ikozader lei: (A 0, 1, 2, 3, 4 s az 5, 6, 7, 8, 9 sorszmok itt // is a kt szerkesztsi alap tszghz kiosztva. 10 s 11 a sorszma // annak a kt cscsnak, amely az ezekre emelt kt gla cscsa.) let ikozaderlek : (int * int) array = [| (0, 1); (1, 2); (2, 3); (3, 4); (4, 0); (0, 10); (1, 10); (2, 10); (3, 10); (4, 10); (0, 8); (1, 8); (1, 9); (2, 9); (2, 5); (3, 5); (3, 6); (4, 6); (4, 7); (0, 7); (5, 6); (6, 7); (7, 8); (8, 9); (9, 5); (5, 11); (6, 11); (7, 11); (8, 11); (9, 11) |] // Az ikozader 20 lapjnak lersa (a -1-ek helykitltk...): let ikozaderLapok : (int * int * int * int * int) array = [| (0, 1, 10, -1, -1); (1, 2, 10, -1, -1); (2, 3, 10, -1, -1); (3, 4, 10, -1, -1); (4, 0, 10, -1, -1); (0, 1, 8, -1, -1); (1, 2, 9, -1, -1); (2, 3, 5, -1, -1); (3, 4, 6, -1, -1); (4, 0, 7, -1, -1); (5, 6, 3, -1, -1); (6, 7, 4, -1, -1); (7, 8, 0, -1, -1); (8, 9, 1, -1, -1); (9, 5, 2, -1, -1); (5, 6, 11, -1, -1); (8, 9, 11, -1, -1); (9, 5, 11, -1, -1); (6, 7, 11, -1, -1); (7, 8, 11, -1, -1) |] Szebb lett volna, ha a laplerk a Kvaterni_mveletek modul hromszg, ngyszg, tszg objektumai. (ppen erre gondolva kerlt be a skidomok deklarcija ebbe a modulba.) Viszont a cscsok kvaternitmbjnek tadsa utn a lapoknak s az leknek a kezelshez csupn annak megadsra volt szksg, hogy az l milyen sorszm cscsokat kt ssze, illetve, hogy a lapon milyen sorszm cscsokat tallunk. Ekkor pedig azt talltuk a legegyszerbbnek, ha olyan adatstruktrkat hasznlunk, amelyeknl az lek a cscsok sorszmainak kettsei (tuples 2 elemmel), a lapok pedig a cscsok sorszmainak tsei (tuples 5 elemmel). Persze, ekkor az tskben egy vagy kt hely nha kihasznlatlanul marad. (A kihasznlatlan helyekre olyan szmot kell tenni, amely nem lehet cscs sorszma. Mivel a programozsi indexels 0-tl indul, valamint a cscsok sorszmozst is 0-tl kezdtk, a kihasznlatlan helyekre clszeren -1-et rtunk.)

84

Kvaternik s alkalmazsuk A szablyos testek szerkesztsnek programozsa ( F# )


A szablyos testek mindegyikt egyformn vezrelhet fggvnnyel rajzoltatjuk. A fggvnyeknek hrom bemen paramtk van: vastag, sznez s a forgat paramter. Az els paramter a drtvz eltrben lev leinek vonalvastagsgt adja meg (most 3-ra van lltva). A drtvz hts vonalait 1 vonalvastagsggal rajzolja a program. sznez paramter true helyzetben a test oldallapjai nem tltszak: az oldallapok festve vannak ( false helyzetben, persze, a drtvzat ltjuk). Vgl forgat paramter true rtke esetn nem csak a kiindulsi alakzatot szerkeszti s rajzoltatja a program, hanem annak egy elforgatottjt is. A programrszletek mkdsnek megrtst a program sorai kz rt magyarzatokkal igyekeztnk biztostani. Mindegyik szablyos alakzathoz kt rajzos oldal tartozik, amelyen a forgat false, illetve true rtknek megfeleltetett lapokon a sznez vltoz false, illetve true rtknek megfelel brkat ltunk.

Tetrader
let Tetrader( vastag : int, sznez : bool, forgat : bool ) = rajz.BackColor <- Color.White Felirat( "Tetrader", 50, 50, 20, Color.DarkCyan ) HomognKoordintaHttr( Color.Gray ) // A tetrader alapja egy sk, amelyen egy egyenes dfspontjaknt // jellnk ki egy pontot: let SkS = Plane( VGTELEN, VGTELEN, EGY ) let EgyenesT = Line( -HAT, -KETT, NGY, -HAT, -KETT, -FL ) let dfsPont = SkotDfEgyenes( SkS, EgyenesT ) // // // // sznez kls vltoz belltstl fggen drtvzat kszt, vagy sznezett fellet testet llt el a fggvny. A sznezssel egytt bizonyos rszleteket (httr sk szne, egyenes s pont kpe) jelentktelentnk, illetve elhagyunk:

if sznez then SkRajz( Color.Silver, SkS, HT ) else SkRajz( Color.Lime, SkS, HT ) EgyenesRajz( Color.Blue, EgyenesT, NULLA ) PontRajz( Color.Red, 2, dfsPont ) // A dfspontot ktszer 120 fokkal elforgatva ellltjuk az alap // szablyos hromszget:

85

Kvaternik s alkalmazsuk
tPontok.[0] <- dfsPont tPontok.[1] <- SkS.Rot120Kvat * tPontok.[0] * SkS.Rot120Kvat.Konj tPontok.[2] <- SkS.Rot120Kvat * tPontok.[1] * SkS.Rot120Kvat.Konj // A szablyos hromszg kt szomszdos pontjnak tvolsga: let oldalHossz = ( tPontok.[1] - tPontok.[0] ).abs // Az egyenlszr hromszg kzppontja az alaplap slypontja: let hromszgSlypontja = ( tPontok.[0] + tPontok.[1] + tPontok.[2] ).Scal(HARMAD) // A slyponthoz mutat vektorhoz a szmtott p hosszsg, az // alaplapra merleges vektort hozzadva ( #Tetrader_magassga ) // a tedradernek az alaplapon kvli cscspontjt megkapjuk: tPontok.[3] <- Kvaterni( EGY, hromszgSlypontja.Vect + SkS.NormVect.Scal( oldalHossz * Math.Sqrt( KETT / HROM ) ) ) let mutable rajzToll = new Pen( Color.Red, float32 vastag ) // Ezzel a fggvnnyel sszektjk (a lthatsgot is figyelembe vve) // a tetrader cscspontjait (a rajzToll piros): if not sznez then lRajz( rajzToll, tetraderlek, tPontok ) if forgat then // Ha kt helyzetben brzoljuk a tetradert, s drtvzat // rajzoltatunk, megsorszmozza a cscsokat: Pontsorszmotr( tPontok, Color.Cyan ) else // Nem tltszv teszi (sznezi) a lapokat: LapRajz( rajzToll, tPontok, tetraderLapok, Sznek ) if forgat then // A tetradert az i tengely krl 160 fokkal elforgatja: let Forgat = Kvaterni( Vector(EGY, NULLA, NULLA), double(160) ) for i = 0 to tPontok.Length - 1 do tPontok.[i] <- Forgat * tPontok.[i] * Forgat.Konj // Kk sznnel megrajzoltatja az j helyzetnek megfelel vzat: rajzToll <- new Pen( Color.Navy, float32 vastag ) if not sznez then lRajz( rajzToll, tetraderlek, tPontok ) // A forgatsi tengelyt rajzoltatjuk kirva a forgats szgt: RRajzol( Forgat, -150, -10, HT, HT ) // Ha kt helyzetben brzoljuk a tetradert, s drtvzat // rajzoltatunk, megsorszmozza a cscsokat: Pontsorszmotr( tPontok, Color.Magenta ) else // Kifesti j helyzetben a tetradert: LapRajz( rajzToll, tPontok, tetraderLapok, Sznek )

86

Kvaternik s alkalmazsuk

87

Kvaternik s alkalmazsuk

88

Kvaternik s alkalmazsuk Oktader


let Oktader( vastag : int, sznez : bool, forgat : bool ) = Felirat( "Oktader", 50, 50, 20, Color.DarkCyan ) HomognKoordintaHttr( Color.Gray ) // k-ra merleges skon lesz a kzp ngyzet: let SkS : Plane = new Plane( VGTELEN, VGTELEN, HROM ) // A fentivel prhuzamos rnykskot is ksztnk: let SkH : Plane = new Plane( VGTELEN, VGTELEN, double -1.25 ) // A skon felvesznk egy pontot, ez lesz a 0. idex cscs: let PontS : Kvaterni = new Kvaterni( EGY, HROM, HROM, HROM ) // Rajzolsok az zemmdtl fggen: if sznez then SkRajz( Color.Silver, SkH, NGY ) else if not forgat then SkRajz( Color.Silver, SkH, NGY ) SkRajz( Color.RoyalBlue, SkS, NGY ) PontRajz( Color.Red, 2, PontS ) // 90 fokos forgatsokkal a tovbbi cscsok szerkesztse: oPontok.[0] oPontok.[1] oPontok.[2] oPontok.[3] <<<<PontS SkS.Rot90Kvat * oPontok.[0] * SkS.Rot90Kvat.Konj SkS.Rot90Kvat * oPontok.[1] * SkS.Rot90Kvat.Konj SkS.Rot90Kvat * oPontok.[2] * SkS.Rot90Kvat.Konj

// Az oktader oldalhossza kt szomszdos cscs tvolsga: let oldalHossz = ( oPontok.[1] - oPontok.[0] ).abs // Kiszmtjuk a ngyzet kzppontjt: let ngyzetSlypontja = ( oPontok.[0] + oPontok.[1] + oPontok.[2] + oPontok.[3] ).Scal(NEGYED) // A ngyzet kzppontjtl kiindulva a ngyzetre merleges // egyenes mentn mindkt irnyban felmrjk a meglev ngyzeten // kvli cscs tvolsgt: a ngyzettl felt.

89

Kvaternik s alkalmazsuk
oPontok.[4] <- Kvaterni( EGY, ngyzetSlypontja.Vect + SkS.NormVect.Scal( oldalHossz / GYKKETT ) ) oPontok.[5] <- Kvaterni( EGY, ngyzetSlypontja.Vect SkS.NormVect.Scal( oldalHossz / GYKKETT ) ) let mutable rajzToll = new Pen( Color.Red, float32 vastag ) // Drtvzat rajzoltatunk, illetve felletet szneztetnk: if not sznez then lRajz( rajzToll, oktaderlek, oPontok ) if forgat then Pontsorszmotr( oPontok, Color.Cyan ) else LapRajz( rajzToll, oPontok, oktaderLapok, Sznek ) // Ha az oktadert kt helyzetben mutatjuk, megszerkesztjk az // elforgatottjt, majd rajzoltatunk: if forgat then // Az oktadert az i - j szgfelez krl 140 fokkal elforgatjuk: let Forgat = Kvaterni( Vector( EGY, EGY, NULLA ), double(140) ) // Az alakzat minden egyes cscspontjn a forgats elvgzse: for i = 0 to oPontok.Length - 1 do oPontok.[i] <- Forgat * oPontok.[i] * Forgat.Konj // Kk sznnel megrajzoltatjuk az j helyzetnek megfelel vzat: rajzToll <- new Pen( Color.Navy, float32 vastag ) if not sznez then lRajz( rajzToll, oktaderlek, oPontok ) RRajzol( Forgat, -350, 100, T, T ) // Ha kt helyzetben brzoljuk az oktadert, s drtvzat // rajzoltatunk, megsorszmozzuk a cscsokat: Pontsorszmotr( oPontok, Color.Magenta ) else // Kifestjk j helyzetben az oktadert: LapRajz( rajzToll, oPontok, oktaderLapok, Sznek )

90

Kvaternik s alkalmazsuk

91

Kvaternik s alkalmazsuk

92

Kvaternik s alkalmazsuk Hexader


let Hexader( vastag : int, sznez : bool, forgat : bool ) = rajz.BackColor <- Color.White Felirat( "Hexader (kocka)", 50, 50, 20, Color.DarkCyan ) HomognKoordintaHttr( Color.Gray ) // j-re merleges skon lesz a kocka ngyzet alapja: let SkS : Plane = Plane( VGTELEN, KILENC, VGTELEN ) // Egy pontot vesznk fel ezen a skon: let PontS : Kvaterni = Kvaterni( EGY, HROM, KILENC, HROM ) // Kirajzoltats a mkdsmdtl fggen: if sznez then SkRajz( Color.Silver, SkS, T ) elif not forgat then SkRajz( Color.DarkKhaki, SkS, T ) PontRajz( Color.DarkRed, 2, PontS ) // A skon a pontot hromszor 90 fokkal elforgatva ellltjuk az // alap ngyzet tovbbi pontjait: hPontok.[0] hPontok.[1] hPontok.[2] hPontok.[3] <<<<PontS SkS.Rot90Kvat * hPontok.[0] * SkS.Rot90Kvat.Konj SkS.Rot90Kvat * hPontok.[1] * SkS.Rot90Kvat.Konj SkS.Rot90Kvat * hPontok.[2] * SkS.Rot90Kvat.Konj

// Kt szomszdos pont tvolsga az oldalhossz: let oldalHossz = ( hPontok.[1] - hPontok.[0] ).abs // Az alap mindegyik cscspontjban az alaplapra merleges irnyban // az oldalhosszat felmrve ellltjuk a tovbbi cscsokat: hPontok.[4] <- Kvaterni( EGY, hPontok.[0].Vect SkS.NormVect.Scal( oldalHossz ) ) hPontok.[5] <- Kvaterni( EGY, hPontok.[1].Vect SkS.NormVect.Scal( oldalHossz ) ) hPontok.[6] <- Kvaterni( EGY, hPontok.[2].Vect SkS.NormVect.Scal( oldalHossz ) ) hPontok.[7] <- Kvaterni( EGY, hPontok.[3].Vect SkS.NormVect.Scal( oldalHossz ) )

93

Kvaternik s alkalmazsuk
let mutable rajzToll = new Pen( Color.Red, float32 vastag ) // Piros szn drtvzat rajzoltatunk, illetve befestjk a kockt: if not sznez then lRajz( rajzToll, hexaderlek, hPontok ) // Forgats esetn midkt drtvzon sorszmozzuk a cscsokat: if forgat then Pontsorszmotr( hPontok, Color.Cyan ) else LapRajz( rajzToll, hPontok, hexaderLapok, Sznek ) // Ha a kockt el is kell forgatni, itt folytatjuk: if forgat then // A hexadert a j - k szgfelez krl 180 fokkal elforgatjuk // A forgatsi kvaterni konstruktort alkalmazzuk: ennek els // paramtere a tengelyt kijell vektor, msodik paramtere // pedig az elforgats szge: let Forgat = Kvaterni( Vector( NULLA, EGY, EGY ), double(180) ) // A kocka mindegyik cscsra alkalmazzuk a forgatsi // transzformcit: for i = 0 to hPontok.Length - 1 do hPontok.[i] <- Forgat * hPontok.[i] * Forgat.Konj // Kk sznnel megrajzoltatjuk az j helyzetnek megfelel vzat: rajzToll <- new Pen( Color.Navy, float32 vastag ) if not sznez then lRajz( rajzToll, hexaderlek, hPontok ) RRajzol( Forgat, 0, 150, double 10.5, KTSFL ) // Megsorszmozzuk a cscsokat: Pontsorszmotr( hPontok, Color.Magenta ) else // Kifestjk j helyzetben is a kockt: LapRajz( rajzToll, hPontok, hexaderLapok, Sznek )

94

Kvaternik s alkalmazsuk

95

Kvaternik s alkalmazsuk

96

Kvaternik s alkalmazsuk Dodekader


let Dodekader( vastag : int, sznez : bool, forgat : bool ) = rajz.BackColor <- Color.White Felirat( "Dodekader", 50, 50, 20, Color.DarkCyan ) HomognKoordintaHttr( Color.Gray ) // A tengelyek metszsi pontjval skot hatrozunk meg: let SkS= new Plane( T, MSFL, KTSFL ) // Egyenest adunk meg a kt trbeli pontjnak koordintival: let EgyenesT = new Line( -EGY, -EGY, -EGY, KETT, EGY, HAT ) // Meghatrozzuk az egyenes dfspontjt a skon: let dfsPont = SkotDfEgyenes( SkS, EgyenesT ) // zemmdtl fggen kirajzoltatunk: if sznez then SkRajz( Color.Silver, SkS, KETT ) elif not forgat then SkRajz( Color.SkyBlue, SkS, KETT ) EgyenesRajz( Color.Blue, EgyenesT, TIZED ) PontRajz( Color.Red, 2, dfsPont ) // // // // A dfspont az alap tszg els cscsa. Elforgatst vgeztetnk a skon ngyszer egyms utn 72 fokkal. (A forgats kzppontja a sknak az orighoz legkzelebbi - Sk.Near - pontja.) Ez a szablyos tszg a dodekader els oldallapja. <<<<<dfsPont SkS.Rot72Kvat SkS.Rot72Kvat SkS.Rot72Kvat SkS.Rot72Kvat

dPontok.[0] dPontok.[1] dPontok.[2] dPontok.[3] dPontok.[4]

* * * *

dPontok.[0] dPontok.[1] dPontok.[2] dPontok.[3]

* * * *

SkS.Rot72Kvat.Konj SkS.Rot72Kvat.Konj SkS.Rot72Kvat.Konj SkS.Rot72Kvat.Konj

// Az tszg oldalhossza (a), tlja (c), valamint az tlhoz tartoz // egyenl oldal hromszg magassga (n) ( #Dodekader_adatai ): let a = ( dPontok.[1] - dPontok.[0] ).abs let c = a * ( EGY + GYKT ) / KETT let n = c * GYKHROMPERKETT // A drtvzas bra tolla: let mutable rajzToll = new Pen( Color.Red, float32 vastag )

97

Kvaternik s alkalmazsuk
// Az alaplapi cscsokkal szomszdos legkzelebbi cscsok // helykoordintjnak (kvaternijnak) szmtsa: let (egyikPont, msikPont) = KtPonttlMegadottTvolsgra(dPontok.[1], Plane( ( dPontok.[0] + dPontok.[2] ).Scal(FL), ( dPontok.[2] - dPontok.[0] ).Vect), a, n ) // A kt megolds kzl az alaplap flttit vlasztjuk: dPontok.[5] <- msikPont let (egyikPont, msikPont) Plane( ( dPontok.[1] + ( dPontok.[3] dPontok.[6] <- msikPont let (egyikPont, msikPont) Plane( ( dPontok.[2] + ( dPontok.[4] dPontok.[7] <- msikPont let (egyikPont, msikPont) Plane( ( dPontok.[3] + ( dPontok.[0] dPontok.[8] <- msikPont let (egyikPont, msikPont) Plane( ( dPontok.[4] + ( dPontok.[1] dPontok.[9] <- msikPont

= KtPonttlMegadottTvolsgra(dPontok.[2], dPontok.[3] ).Scal(FL), dPontok.[1] ).Vect), a, n ) = KtPonttlMegadottTvolsgra(dPontok.[3], dPontok.[4] ).Scal(FL), dPontok.[2] ).Vect), a, n ) = KtPonttlMegadottTvolsgra(dPontok.[4], dPontok.[0] ).Scal(FL), dPontok.[3] ).Vect), a, n ) = KtPonttlMegadottTvolsgra(dPontok.[0], dPontok.[1] ).Scal(FL), dPontok.[4] ).Vect), a, n )

// Emlkeztet segdvonalak berajzolsa a drtvzas brba: if not forgat sszekt( sszekt( sszekt( sszekt( && not sznez then Pens.Cyan, dPontok.[4], dPontok.[9] ) Pens.Cyan, dPontok.[1], dPontok.[9] ) Pens.Cyan, dPontok.[1], dPontok.[4] ) Pens.Cyan, dPontok.[0], ( dPontok.[1] + dPontok.[4] ).Scal(FL))

// Az alaphoz illeszked oldallapi tszgek skjban az oldallapi // tszgek tdik cscsa (amely a szomszdos cscsoktl 'a' // tvolsgra van) helykoordintjnak (kvaternijnak) meghatrozsa: let (egyikPont, msikPont) = KtPonttlMegadottTvolsgra(dPontok.[5], Plane( dPontok.[6], dPontok.[1], dPontok.[2] ), a, a ) // A kt megolds kzl a megfelel kivlasztsa: dPontok.[10] <- egyikPont let (egyikPont, msikPont) = KtPonttlMegadottTvolsgra(dPontok.[6], Plane( dPontok.[7], dPontok.[2], dPontok.[3] ), a, a ) dPontok.[11] <- egyikPont let (egyikPont, msikPont) = KtPonttlMegadottTvolsgra(dPontok.[7],

98

Kvaternik s alkalmazsuk
Plane( dPontok.[8], dPontok.[3], dPontok.[4] ), a, a ) dPontok.[12] <- egyikPont let (egyikPont, msikPont) = KtPonttlMegadottTvolsgra(dPontok.[8], Plane( dPontok.[9], dPontok.[4], dPontok.[0] ), a, a ) dPontok.[13] <- egyikPont let (egyikPont, msikPont) = KtPonttlMegadottTvolsgra(dPontok.[9], Plane( dPontok.[5], dPontok.[0], dPontok.[1] ), a, a ) dPontok.[14] <- egyikPont // A dodekader-test kzppontjnak meghatrozsa az utbbi 10 pont // koordintjnak (kvaternijnak) tlagolsval: let mutable kzepe = O for lI = 5 to 14 do kzepe <- kzepe + dPontok.[lI] kzepe <- kzepe.Scal(TIZED) // Az utols 5 pont kvaternijt a kiindulsi alaplap 5 kvaternijnak // a testkzpen keresztl val tkrzsvel szmtjuk ki: for lI = 15 to 19 do dPontok.[lI] <- KzppontosTkrzs( kzepe, dPontok.[lI - 15] ) // zemmdtl fggen rajzoltats: if not sznez then lRajz( rajzToll, dodekaderlek, dPontok ) if forgat then Pontsorszmotr( dPontok, Color.Cyan ) else PontRajz( Color.DarkCyan, 2, kzepe ) else LapRajz( rajzToll, dPontok, dodekaderLapok, Sznek ) if forgat then // A dodekadert a k tengely krl -200 fokkal elforgatjuk: let Forgat = Kvaterni(Vector(NULLA, NULLA, EGY), double(-200)) for i = 0 to dPontok.Length - 1 do dPontok.[i] <- Forgat * dPontok.[i] * Forgat.Konj // Kk sznnel megrajzoltatjuk az j helyzetnek megfelel vzat: rajzToll <- new Pen( Color.Navy, float32 vastag ) if not sznez then lRajz( rajzToll, dodekaderlek, dPontok ) RRajzol( Forgat, 50, 100, HAT, TZ ) // Ha kt helyzetben brzoljuk a dodekadert, s drtvzat // rajzoltatunk, megsorszmozzuk a cscsokat: Pontsorszmotr( dPontok, Color.Magenta ) else // Kifesti j helyzetben a dodekadert: LapRajz( rajzToll, dPontok, dodekaderLapok, Sznek )

99

Kvaternik s alkalmazsuk

100

Kvaternik s alkalmazsuk

101

Kvaternik s alkalmazsuk Ikozader


let Ikozader( vastag : int, sznez : bool, forgat : bool ) = rajz.BackColor <- Color.White Felirat( "Ikozader", 50, 50, 20, Color.DarkCyan ) HomognKoordintaHttr( Color.Gray ) // Az ikozader egyik szablyos tszg metszetnek skja: let SkS = Plane( VGTELEN, VGTELEN, FL ) let SkH = Plane( VGTELEN, VGTELEN, double 2.1 ) // k tengellyel prhuzamos egyenes, amely az egyik cscsot a skon // kijelli (dfsPont): let EgyenesT = Line (-HROM, -HROM, NULLA, -HROM, -HROM, HROM ) let dfsPont = SkotDfEgyenes( SkS, EgyenesT ) // zemmdtl fgg rajzoltats: if sznez then SkRajz( Color.Silver, SkH, NGY ) elif not forgat then SkRajz( Color.Silver, SkH, NGY ) SkRajz( Color.SkyBlue, SkS, NGY ) EgyenesRajz( Color.Blue, EgyenesT, TIZED ) PontRajz( Color.Red, 2, dfsPont ) // Szablyos tszg szerkesztse forgatsokkal: iPontok.[0] <- dfsPont iPontok.[1] <- SkS.Rot72Kvat * iPontok.[0] * SkS.Rot72Kvat.Konj iPontok.[2] <- SkS.Rot72Kvat * iPontok.[1] * SkS.Rot72Kvat.Konj iPontok.[3] <- SkS.Rot72Kvat * iPontok.[2] * SkS.Rot72Kvat.Konj iPontok.[4] <- SkS.Rot72Kvat * iPontok.[3] * SkS.Rot72Kvat.Konj // Az tszg slypontjnak meghatrozsa a cscsponti kvaternik // tlagolsval: let tszgSlypontja = ( iPontok.[0] + iPontok.[1] + iPontok.[2] + iPontok.[3] + iPontok.[4] ).Scal( EGY / T ) // Az alap tszg cscsainak kzppontos tkrzsvel a vele // prhuzamosan elhelyezked bels tszg alapra vettett // cscspontjainak meghatrozsa: for lI = 0 to 4 do iPontok.[5 + lI] <KzppontosTkrzs( tszgSlypontja, iPontok.[lI] )

102

Kvaternik s alkalmazsuk
// // // // // // // let let let let let let let let Az tszg oldalhossza (a); tlja (c); egy szmtsi segdmennyisg (s); a szablyos tszg magassga (b); a szablyos tszg oldalhoz tartoz egyenl oldal hromszg magassga (m); az tszg krlrt krnek sugara (r); az ikozaderbl leszelhet tszg alap glk magassga (q); vgl a tetraderben fellelhet egymssal prhuzamos skokon elhelyezked szablyos tszgek skjnak egymstl mrt tvolsga (t) ( levezets: #Dodekader_adatai, #Ikozader_adatai ): a c s b m r q t = = = = = = = = ( iPontok.[1] - iPontok.[0] ).abs a * ( EGY + GYKT ) / KETT T + KETT * GYKT a / KETT * Math.Sqrt( s ) a * GYKHROMPERKETT a / KETT * ( HROM + GYKT ) / Math.Sqrt( s ) a / KETT * Math.Sqrt( ( HAT + KETT * GYKT ) / ( s ) ) a / KETT * Math.Sqrt( ( double 14 + HAT * GYKT ) / ( s ) )

// A drtvz rajzolshoz toll: let mutable rajzToll = new Pen( Color.Red, float32 vastag ) // A kiindulsi tszg skjn megszerkesztett tkrztt segdpontok // (vetleti pontok) felhasznlsval az alappal prhuzamos (tle t // tvolsgra lev) pontok ellltsa: let tvVektor = SkS.NormVect.Scal( t ) iPontok.[8] iPontok.[9] iPontok.[5] iPontok.[6] iPontok.[7] <<<<<Kvaterni( Kvaterni( Kvaterni( Kvaterni( Kvaterni( EGY, EGY, EGY, EGY, EGY, iPontok.[8].Vect iPontok.[9].Vect iPontok.[5].Vect iPontok.[6].Vect iPontok.[7].Vect + + + + + tvVektor tvVektor tvVektor tvVektor tvVektor ) ) ) ) )

// Ennek a szablyos tszgnek is meghatrozzuk a kzppontjt: let msikSlypontja = ( iPontok.[5] + iPontok.[6] + iPontok.[7] + iPontok.[8] + iPontok.[9] ).Scal(TD) // // // // A szablyos tszgekre mint alapokra pl glk cscsnak kiszmtsa a q magassg mret normlis irny vektornak az egyik slypont vektorhoz val hozzadsval, illetve a msikbl val levonssal:

let cscsVektor = SkS.NormVect.Scal( q ) iPontok.[10] <- Kvaterni( EGY, tszgSlypontja.Vect cscsVektor) iPontok.[11] <- Kvaterni( EGY, msikSlypontja.Vect + cscsVektor )

103

Kvaternik s alkalmazsuk
// Az ikozader ellltsa a paramtereknek megfelelen: if not sznez then // Csak az lek drtvzszer kihzsa: lRajz( rajzToll, ikozaderlek, iPontok ) // lRajzKzi( rajzToll, ikozaderlek, iPontok, [| 3; 4; 6 |] ) if forgat then // Ha kt helyzetben brzoljuk az ikozadert, s drtvzat // rajzoltatunk, megsorszmozzuk a cscsokat: Pontsorszmotr( iPontok, Color.Cyan ) else // A felletek festsvel: LapRajz( rajzToll, iPontok, ikozaderLapok, Sznek ) // LapRajzKzi( rajzToll, iPontok, ikozaderLapok, // [| 3; 4; 6 |], Sznek) if forgat then // Az ikozadert a j tengely krl 130 fokkal elforgatjuk: let Forgat = Kvaterni(Vector(NULLA, EGY, NULLA), double(130)) // Az ikozader mindegyik cscsra alkalmazzuk a forgat // transzformcit: for i = 0 to iPontok.Length - 1 do iPontok.[i] <- Forgat * iPontok.[i] * Forgat.Konj // Kk sznnel megrajzoltatjuk az j helyzetnek megfelel vzat: rajzToll <- new Pen( Color.Navy, float32 vastag ) if not sznez then lRajz( rajzToll, ikozaderlek, iPontok ) RRajzol( Forgat, -500, 200, KILENC, NYOLC ) Pontsorszmotr( iPontok, Color.Magenta ) else // Kifesti j helyzetben az ikozadert: LapRajz( rajzToll, iPontok, ikozaderLapok, Sznek ) Az ikozadert mutat ngy brt kvet oldalakon mellkeljk az lek rajzoltatst vgz fggvny egy egyszerstett megvalstst, amelynl a httrbe helyezend cscsok (amelyekhez men leket vkonytjuk) sorszmt paramterknt adjuk t (mint a fentiekben a lap tetejn magyarzat sorknt a kdban elhelyezett fggvnyhvs esetn). Hasonlkppen a felletek sznezst vgz fggvnynek is megmutatjuk egy olyan vltozatt, amely kzi mdon lltja be a felletek lthatsgt, azaz az elz fggvnyhez hasonlan ez is tveszi azt a tmbt, amely az eltakart cscsokat tartalmazza (hvsa a lap kzepn lthat). Vgl kzreadjuk azt a fggvnyt is, amelyre az elz fggvnyek hivatkoznak, s amely a KoordintaHttr ltrehozst vgzi.

104

Kvaternik s alkalmazsuk

105

Kvaternik s alkalmazsuk

106

Kvaternik s alkalmazsuk
let lRajzKzi( fToll : Pen, flek : ( int * int ) array, fPontok : Kvaterni array, fTakart : int array ) = let mutable lI : int = 0 let mutable lJ : int = 0 let mutable lK : int = 0 let mutable lHts : bool = false // A kvaternival megadott cscspontok helyett a tovbbiakban a rajz // skjban rvnyes pontkoordintkat hasznljuk: let lPontok : PointF array = Array.zeroCreate fPontok.Length for lI = 0 to fPontok.Length - 1 do let (lX, lY, lZ) = KvaterniPont(fPontok.[lI]) lPontok.[lI].X <- float32 lX lPontok.[lI].Y <- float32 lY // // // // // Megrajzoltatjuk a paramterknt tadott tollal valamennyi, a szablyos testhez tartozan felsorolt let. Pontosabban: a toll sznvel, de egysgnyi vonalvastagsggal rajzoltatunk, ha az l takart pontbl indul, illetve abba rkezik, csak a tbbi l esetben hagyjuk meg a megadott vonalvastagsgot.

for lI = 0 to flek.Length - 1 do let ( lEzt, lEzzel ) = flek.[lI] lHts <- false lJ <- 0 while not lHts && lJ < fTakart.Length do lK <- fTakart.[lJ] if lEzt = lK || lEzzel = lK then lHts <- true lJ <- lJ + 1 if lHts then bra.DrawLine( new Pen(fToll.Color), lPontok.[lEzt], lPontok.[lEzzel] ) else bra.DrawLine( fToll, lPontok.[lEzt], lPontok.[lEzzel] ) // Az tadott (legfeljebb 5 cscsponttal meghatrozott) lap takart-e: let Rajzolja( ( A, B, C, D, E ) : int * int * int * int * int, fTakart : int array ) : bool = // Bels fggvny, amely azt nzi, hogy a paramterknt tadott // sorszm cscs fedett (takart)-e: let Takart( cscsSorszm : int ) : bool = let mutable lI : int = 0

107

Kvaternik s alkalmazsuk
let mutable lTakart: bool = false // Negatv cscssorszm ll az "res" helyeken: if cscsSorszm > 0 then lI <- 0 while lI < fTakart.Length && not lTakart do if cscsSorszm = fTakart.[lI] then lTakart <- true lI <- lI + 1 lTakart not ( Takart(A) || Takart(B) || Takart(C) || Takart(D) || Takart(E) ) // A lapok sznezst vgz fggvny, amely paramterknt a takart cscsok // listjt (s persze a lapok szneinek tmbjt) megkapja: let LapRajzKzi( fToll : Pen, fPontok : Kvaterni array, fLapok: ( int * int * int * int * int ) array, fTakart : int array, fSznek : Color array ) = // Bels fggvny, amely az indexek listjn szerepl soszm // cscspontok ltal meghatrozott lapokat sznezi. let LapFest( fEcset : Brush, lIndexek : int array ) = let mutable lI : int = 0 let rajzPontok : Point array = Array.zeroCreate ( lIndexek.Length + 1 ) for lI = 0 to lIndexek.Length - 1 do let ( pontX, pontY, pontZ ) = KvaterniPont( fPontok.[lIndexek.[lI]] ) rajzPontok.[lI].X <- pontX rajzPontok.[lI].Y <- pontY rajzPontok.[lIndexek.Length] <- rajzPontok.[0] bra.FillPolygon( fEcset, rajzPontok ) let mutable lI as int = 0 // A szablyos test mindegyik lapjt vizsglja. Amelyik lapnak van // olyan cscsa, amely a takart cscsok listjn szerepel, azt a // lapot nem festi a program. A lapok sznezsre egybknt a sznek // kzl a lap sorszmnak megfelel sorszmt vlasztja. for lI = 0 to fLapok.Length - 1 do // A lap cscsainak tst ttlti az ( A, B, C, D, E ) tsbe: let ( A, B, C, D, E ) = fLapok.[lI] if Rajzolja( ( A, B, C, D, E ), fTakart ) then if E < 0 then if D < 0 then LapFest( new SolidBrush( fSznek.[lI]), [| A; B; C |] ) else LapFest( new SolidBrush( fSznek.[lI]), [| A; B; C; D |] ) else

108

Kvaternik s alkalmazsuk
LapFest( new SolidBrush( fSznek.[lI]), [| A; B; C; D; E |] ) // Fggvny, amely a rajzokon a koordintarendszert elhelyezi: let HomognKoordintaHttr( ByVal vltozSzn : Color ) = // Sznek s tollak defincija: let egysgSzn : Color = vltozSzn let tengelySzn : Color = vltozSzn let tengelyToll : Pen = new Pen( tengelySzn, float32 3 ) let vkonyToll : Pen = new Pen( vltozSzn, float32 1 ) let pirosToll : Pen = new Pen( Color.Red, float32 1 ) // F tengelyszakaszok rajzoltatsa: bra.DrawLine( tengelyToll, tr4Ox, tr4Oy, bra.DrawLine( tengelyToll, tr4Ox, tr4Oy, bra.DrawLine( tengelyToll, tr4Ox, tr4Oy, bra.DrawLine( tengelyToll, tr4Ox, tr4Oy,

tr4Rx, tr4Ix, tr4Jx, tr4Kx,

tr4Ry tr4Iy tr4Jy tr4Ky

) ) ) )

// Tengelyek (vkony vonalas) meghosszabbtsa: bra.DrawLine( vkonyToll, tr4Ox, tr4Oy, 2 * tr4Ox - tr4Rx, 2 * tr4Oy - tr4Ry ) bra.DrawLine( vkonyToll, tr4Ox, tr4Oy, 2 * tr4Ox - tr4Ix, 2 * tr4Oy - tr4Iy ) bra.DrawLine( vkonyToll, tr4Ox, tr4Oy, tr4Ox + (tr4Ox - tr4Jx) / 2, tr4Oy + (tr4Oy - tr4Jy) / 2 ) bra.DrawLine( vkonyToll, tr4Ox, tr4Oy, tr4Ox + (tr4Ox - tr4Kx) / 2, tr4Oy + (tr4Oy - tr4Ky) / 2 ) // Tengelyfeliratok elhelyezse: Felirat( "vals tengely", tr4Rx, tr4Ry - 20, 16, tengelySzn ) Felirat( "kpzetes (i) tengely", tr4Ix - 50, tr4Iy - 30, 16, tengelySzn ) Felirat( "kpzetes (j) tengely", tr4Jx - 40, tr4Jy - 30, 16, tengelySzn ) Felirat( "kpzetes (k) tengely", tr4Kx - 150, tr4Ky - 30, 16, tengelySzn ) // Tengelyek (kis vonalks) keresztlhzsa az egysgeknl: let egyRx = tr4Ox + int(double(tr4Rx - tr4Ox) / SKLA) let egyRy = tr4Oy + int(double(tr4Ry - tr4Oy) / SKLA) KeresztlHz( tengelyToll, 6.0, egyRx, egyRy, tr4Ix, tr4Iy ) let egyIx = tr4Ox + int(double(tr4Ix - tr4Ox) / SKLA) let egyIy = tr4Oy + int(double(tr4Iy - tr4Oy) / SKLA) KeresztlHz( tengelyToll, 6.0, egyIx, egyIy, tr4Rx, tr4Ry ) let egyJx = tr4Ox + int(double(tr4Jx - tr4Ox) / SKLA) let egyJy = tr4Oy + int(double(tr4Jy - tr4Oy) / SKLA) KeresztlHz( tengelyToll, 6.0, egyJx, egyJy, tr4Rx, tr4Ry )

109

Kvaternik s alkalmazsuk
let egyKx = tr4Ox + int(double(tr4Kx - tr4Ox) / SKLA) let egyKy = tr4Oy + int(double(tr4Ky - tr4Oy) / SKLA) KeresztlHz( tengelyToll, 6.0, egyKx, egyKy, tr4Ix, tr4Iy ) // Homogn koordintatengelyek berajzolsa Base0-hoz: bra.DrawLine(pirosToll, egyRx, egyRy, egyRx + tr4Ix - tr4Ox, egyRy + tr4Iy - tr4Oy ) bra.DrawLine(pirosToll, egyRx, egyRy, egyRx + tr4Jx - tr4Ox, egyRy + tr4Jy - tr4Oy ) bra.DrawLine(pirosToll, egyRx, egyRy, egyRx + tr4Kx - tr4Ox, egyRy + tr4Ky - tr4Oy ) bra.DrawLine(pirosToll, egyRx, egyRy, egyRx + tr4Ox - tr4Ix, egyRy + tr4Oy - tr4Iy ) bra.DrawLine(pirosToll, egyRx, egyRy, egyRx + 2 *(tr4Ox - tr4Jx)\ 3, egyRy + 2 *(tr4Oy - tr4Jy)\ 3 ) bra.DrawLine(pirosToll, egyRx, egyRy, egyRx + (tr4Ox - tr4Kx) \ 2, egyRy + (tr4Oy - tr4Ky) \ 2 ) // Az egysgekhez (s az origo ponthoz) felirat kszttetse: SzimplaFelirat( "1", egyRx, egyRy - 30, 20, egysgSzn ) KvaterniFelirat( "i", egyIx - 10, egyIy - 30, 20, egysgSzn ) KvaterniFelirat( "j", egyJx - 10, egyJy - 40, 20, egysgSzn ) KvaterniFelirat( "k", egyKx - 5, egyKy - 35, 20, egysgSzn ) KvaterniFelirat( "o", tr4Ox - 12, tr4Oy, 20, Color.Magenta )

110

Kvaternik s alkalmazsuk Konkv testek rajzolsa


Ha nem csak konvex testekkel foglalkozunk, a szablyos testekbl rdekes, kinvsekkel rendelkez testekhez juthatunk. Pldul kzenfekv, hogy a dodekader nmelyik szablyos tszg lapjhoz msik dodekadert ragasszunk, gy akr dodekaderekbl alkotott hossz lncokat is kszthetnk. Viszont, ha megktjk a keznket azzal, hogy csak kzppontosan szimmetrikus, minden korbbi lapja irnyban ugyangy folytatott, nmagba nem harap, szablyos testeket rajzoltatunk, akkor hromszgre clszeren tetradert, ngyzetre az oktader felnek megfelel testet, tszgre pedig az ikozadernl szerkesztett glt helyeznk folytatskppen. Ezzel olyan testhez jutunk, amelyik konkv, de csupa egybevg szablyos hromszg hatrolja. Ilyen testekre mutatunk pr pldt ebben a fejezetben. Lthatjk, hogy ezek trbeli forgatsa is nagyon egyszer a kvaternis lers esetn. A lthatsg (takars) krdse mr nem ilyen egyszer. Konvex testeknl kimondhattuk, hogy az az l, amelynek legalbb egyik vgn olyan takart pont tallhat, amely nem a kontron van, teht teljesen takart, nem lthat. Konkv testek esetn egy lnek lehet lthat s nem lthat szakasza. Hasonlkppen a lapoknl: teljesen takart (nem a kontron tallhat) cscsot tartalmaz lap nem lthat konvex testeknl, de az ilyen lapnak is lehet lthat rsze, ha a test nem konvex. A kvetkez kt oldalon a szablyos testek mindegyikt gy bvtjk, hogy br konkvak lesznek csupa egybevg hromszg (tetradernl 12, oktadernl, hexadernl 24, dodekadernl s ikozadernl 60) bortja azokat. (A lthatsgot csak rszben tudjuk figyelembe venni.)

111

Kvaternik s alkalmazsuk

112

Kvaternik s alkalmazsuk

113

Kvaternik s alkalmazsuk
A komplex szmok alkalmazsaknt skbeli fraktlokat rajzoltattunk. Trbeli fraktlokat jl tudunk kezelni a kvaternikkal. Pldul az albbiakban egy, a skbeli Koch grbhez hasonl trbeli fraktlt rajzoltatunk. (Ott egy szakasz harmadolsval indtottunk, s a szakasz harmadt helyettestettk hromszggel, itt pedig minden egyes lap negyedt helyettestjk tetraderrel.) Tetraderbl indulunk ki. Ennek mindegyik oldallapjn kijelljk az oldalfelez pontokat. A felezpontokat egymssal sszektve az oldallapokat ngy darab fele akkora mret hromszgre bontjuk fel. A kzps, szablyos hromszg helyre egy ugyanolyan alap, kifel emelked tetradert helyeznk. Ezt az eljrst egyms utn tbbszr vgrehajthatjuk az ellltott testet hatrol valamennyi hromszg mindegyik oldalnak ismtelt felezsvel s a kzps hromszg tetraderrel helyettestsvel. Az albbi brkon elszr a legbonyolultabb kpet mutatjuk, majd utna (visszafel) az elz kt lpst. (A kiindulsi bra, persze, a piros tetrader volt.)

114

Kvaternik s alkalmazsuk

115

Kvaternik s alkalmazsuk Elforgatott pontokbl a forgatsi tengely s szg meghatrozsa


a forgat kvaterni ( #Forgatsi_transzformci ), amelyben egysgvektor a forgats tengelye, szg pedig az elforgats szgnek fele, azt a krdst vetjk fel, hogy s ismeretben ki tudjuk-e szmtani x, y, z-t, valamint meg tudjuk-e hatrozni t? Mindenekeltt a vektorilis szorzat kvaternimveletekkel val lerst msoljuk ide: ( )

Most emlkezznk a forgats bevezet gondolatmenetre! A pontot, amelyet elforgatunk, jobbrl szorozzuk egy kvaternival, ugyanakkor az elforgatott pontot balrl szorozzuk ugyanazzal a kvaternival. Azt lltottuk, hogy a kt szorzat egy (egymssal megegyez) tmeneti pont:

Az elz kpletbe rjuk be ezt az sszefggst azrt, hogy a kvaterni-szorzs elvgzse eltt kiemelsre legynk kpesek: ( ) ( )

A kzps kifejezs kvaterni-szorzst elvgezzk. Figyelembe vesszk, hogy hiszen (mivel kvaterni a kvaterni elforgatottja, ezek vals rsze megegyezik) a kvaternik klnbsge kpzetes vektoraik klnbsge. Ezutn a vektorilis szorzatokat sszevonjuk. ( ) ( Egyrszt bevezetjk a msrszt a ( ( ) ( ( ) ) ( ( ) ) ( ) ( )

s a ) )

, jellst. Behelyettestnk: | ): |

A vals rsz egyetlen, bal oldali tagjnak a jobb oldalon 0 felel meg ( de ( )

Majd kvaterni-komponensenknt sszehasonltjuk a bal oldali s a jobb oldali egytthatkat: ( ( ( ) ) )

116

Kvaternik s alkalmazsuk
Legyen akkor egyenleteink:

A fenti homogn lineris egyenletrendszer egyenletei nem linerisan fggetlenek egymstl, gy a trivilistl eltr megolds ltezik. Tbb sszetartoz pontpr segtsgvel ebbl a homogn lineris egyenletrendszerbl megoldst nyerhetnk. ( x, y, z -t egyrtelmsti az egysgvektorr alakts.) Bztatbb (s egyszerbb) a geometriai mdszer. Az elforgats sorn egy-egy pont helyvltoztatsi vektora a forgatsi tengelyre merleges. Kt ilyen helyvltoztatsi vektor vektorilis szorzata megadja a tengelyirnyt. A tengely az orign megy t, ezrt a tengely egyenesnek egyenlett meghatrozhatjuk. A pontok a tengelyre merleges skban mozognak a forgats sorn. Felvehetnk egy ilyen skot, meghatrozhatjuk a sk tengelypontjt. Az eredeti pontot a tengelyponttal sszekt irny s az elforgatott pontot a tengelyponttal sszekt irny hajlsszge a forgats szge. Az albbiakban lthatjk az F# programot, tovbb a programban pldaknt felhasznlt esetnek (tetrader forgatsa) megfelel rajzot. let ForgatsiTengely(sznez : bool) = let tjPontok : Kvaterni array = [| O; O; O; O|] Felirat("Tetrader", 200, 100, 20, Color.DarkCyan) HomognKoordintaHttr( Color.Gray ) // Pldul szolgl test ( #Tetrader_szerkesztse ): let SkS = Plane(EGY, T, HROM) let EgyenesT = Line(-EGY, NGY, NGY, HAT, NGY, NGY) let dfsPont = SkotDfEgyenes(SkS, EgyenesT) tPontok.[0] <- dfsPont tPontok.[1] <- SkS.Rot120Kvat * tPontok.[0] * SkS.Rot120Kvat.Konj tPontok.[2] <- SkS.Rot120Kvat * tPontok.[1] * SkS.Rot120Kvat.Konj let skSlypontja = (tPontok.[0] + tPontok.[1] + tPontok.[2]).Scal(EGY / HROM) tPontok.[3] <- Kvaterni(EGY, skSlypontja.Vect + SkS.NormVect.Scal((tPontok.[1] - tPontok.[0]).abs * Math.Sqrt(KETT / HROM))) let mutable rajzToll = new Pen(Color.Red, float32 4) lRajz(rajzToll, tetraderlek, tPontok) Pontsorszmotr(tPontok, Color.Cyan)

117

Kvaternik s alkalmazsuk
// Forgat kvaterni ltrehozsa (konstruktorral) s a forgats // vgrehajtsa (i, j szgfelezje a tengelyirny, 75 a szg): let Forgat = Kvaterni( Vector(GYKKETTPERKETT, GYKKETTPERKETT, NULLA), double 75 ) for lI = 0 to tPontok.Length-1 do tjPontok.[lI] <- Forgat * tPontok.[lI] * Forgat.Konj rajzToll <- new Pen(Color.Navy, float32 4) lRajz(rajzToll, tetraderlek, tjPontok) Pontsorszmotr(tjPontok, Color.Magenta) // Fordtott mvelet: a tengely s a szg meghatrozsa: // A tengely irnyvektora kt pont (az 1. s a 2. sorszm) // elmozdulsvektornak vektorilis szorzata: let tengelyIrny = ((tPontok.[1].Vect - tjPontok.[1].Vect) * (tPontok.[3].Vect - tjPontok.[3].Vect)).Unit // A tengely az orign megy t, gy a tengely egyenes elllthat: let tengelyEgyenes = Line(O, tengelyIrny) EgyenesRajz(Color.Indigo, tengelyEgyenes, MSFL) // Az alakzat egyik (3. sorszm) pontjra a tengelyre merleges // skot fektetnk: let egyikSk = Plane(tPontok.[3], tengelyIrny) // A sk tengelypontja a sk s a tengely egyenesnek dfspontjaknt // hatrozhat meg: let dfi = SkotDfEgyenes(egyikSk, tengelyEgyenes)

// Az alakzat adott skhoz tartoz nem elforgatott pontja s a // dfspont egy irnyvektort szolgltat: let vektorEltte = tjPontok.[3].Vect - dfi.Vect // Az alakzat adott skhoz tartoz elforgatott pontja s a // dfspont egy msodik irnyvektort szolgltat: let vektorUtna = tPontok.[3].Vect - dfi.Vect

// Az irnyvektorok vektorilis szorzatnak abszolt rtkbl a // forgatsi szg szinusza, majd a forgatsi szg kiaddik: let szg = VBLFOK * Math.Asin((vektorEltte * vektorUtna).abs / vektorEltte.abs / vektorUtna.abs)

118

Kvaternik s alkalmazsuk
Felirat("Forgatsi tengely: " + tengelyIrny.iComp.ToString("0.000") + " * i + " + tengelyIrny.jComp.ToString("0.000") + " * j + " + tengelyIrny.kComp.ToString("0.000") + " * k", 100, 150, 16, Color.Brown) Felirat("Forgats szge: " + szg.ToString("0.000"), 100, 200, 16, Color.Brown) Termszetesen ennl a szmtsnl is elfordulhat, hogy nem kapunk eredmnyt. Ennek oka pldul az lehet, hogy a kivlasztott kt pont egymssal prhuzamos plyn mozdult el az elforgats sorn, akkor a tengely irnyvektora ezzel a kt ponttal nem szmthat. (Persze, betehetnk a programba olyan feltteles kifejezst, amely ezt a vizsglatot is elvgzi, s olyankor, ha ez bekvetkezik, msik kiindulsi pontot vlaszt.)

119

Kvaternik s alkalmazsuk

Konvergencia-fraktlok
A komplex konvergencia-fraktlok a kvaternikkal ugyangy megfigyelhetk. Pldul a vals tengely s az kpzetes tengely ltal meghatrozott koordinta-skon ( ; ). Msrszt itt megvizsgljuk a trbeli (kvaternikon alapul) fraktl szmtst is. Termszetesen a kvaternik ngyzet-fggvnyt hasznlva a Mandelbrot halmaz trbeli megfeleljt lthatnnk. Mivel ennek brzolsa nem egyszer feladat, az albbiakban ennek skmetszeteit mutatjuk meg. A metsz skok felvtele, persze, nknyes. Arra trekednk, hogy fantzink segtsgvel a fekete testet a metszetek alapjn minl jobban el tudjuk kpzelni. Az albbi brn a metszskok pontjainak halmazt ler kpleteket s a metszskok elhelyezst mutat rajzot lthatnak. Az sszetartozst a sznezssel prbltuk rzkeltetni. A tovbbi lapokon pedig azokat az brkat lthatjk, amelyeket az egyes metszskokon llthatunk el. (Mindegyik metszet fltt a sorozat elemeinek ellltsra szolgl kpletet ltjk.)

120

Kvaternik s alkalmazsuk

121

Kvaternik s alkalmazsuk

122

Kvaternik s alkalmazsuk

123

Kvaternik s alkalmazsuk

124

Kvaternik s alkalmazsuk

125

Kvaternik s alkalmazsuk

126

Kvaternik s alkalmazsuk

127

Kvaternik s alkalmazsuk
Termszetesen mivel az s k szerepe a kvaterniknl teljesen szimmetrikus, helyett a vagy a koordinta alkalmazsval pontosan ugyanilyen metszetekhez jutnnk. (Az alakzat szimmetriatengelye a vals tengely.) Az albbi rajz vzlatosan mutatja az egyes komplex szmskokon lthat Mandelbrot halmazokat. A lila az s a vals, a sttvrs a s a vals, a zld a s a vals tengely ltal kifesztett skon mutatja (csupn jelzs rtken) a Mandelbrot halmaz elhelyezkedst.

Bizony, a kvaterni konvergencia-fraktlok kezelse nem olyan egyszer, mint a komplex konvergencia-fraktlok! Maga a Mandelbrot-halmaznak megfelel rcsks test trbeli kpe esetleg megrajzolhat volna, de csak metszetek ksztsvel (a rteg-rntgenek mintjra) tudnnk olyan ltvnyos rajzokat kszteni, mint komplex esetben (ahogyan ezt az elz brkon lthatjk). Elkpzelhet, hogy ms utat kellene vlasztani! Esetleg olyan skbeli brkat kellene kszteni, amelyeknl az egyik tengely a vals rsz, a msik pedig a kpzetes rsz abszolt rtke. (Hiszen a kpzetes rsz hrom komponensnek teljesen szimmetrikus a hatsa.) Azt mindenesetre kiprbltam, hogy illetve metszskban a konvergenciahalmaznak nincs kknleges szerkezete, krszimmetrikus brkat kapunk. Msrszt a fekete kr mrete fgg a vals sszetev (mint paramter) rtktl.

128

Kvaternik s alkalmazsuk sszefoglals


A kvaternikat felhasznlsuk szempontjbl tbb csoportba sorolhatjuk: lehetnek a szoksos hromdimenzis tereinkhez tartoz trkvaternik, skkvaternik valamint forgat kvaternik. A forgat kvaternit clszeren mindig egysg kvaterniknt vlasztjuk (egybknt a forgats sorn szmtott szorzat sszetevit a forgat kvaterni abszolt rtknek ngyzetvel is osztani kellene). Egysg forgat kvaterni vals rsze a forgatsi szg felnek koszinusza, kpzetes rsze ugyanezen szg szinuszval szorozva a forgats tengelynek egysgvektora. Forgat kvaterni minden egysg vektorkvaterni (tisztn kpzetes kvaterni) is, amely a vektor irnynak megfelel, orign tmen tengely krl 180-kal forgat, illetve (mert ez ugyanazt jelenti) e tengelyre vonatkozlag tengelyes tkrzst vgez. Kt ilyen, egysg vektorkvaternival kijellt tengely tkrzs egymsutnja a kt vektor szgnek dupljval elvgzett forgatst eredmnyez. Ez az elforgats vgrehajthat a kt vektorkvaterni sszeszorzsval nyert forgat kvaternival is. A skkvaternik nem a trkvaternik ktdimenzis szktsei, hanem a tr skjai lersra szolgl ngy egytthat sszefogsra szolgl szerkezetek. Olyan kvaternik, amelyeknek kpzetes vektor rsze egysgvektor, vals rsze pedig negatv szm. (Orign tmen sk esetn a vals rsz nulla. Ebben az esetben formlisan a skkvaterni vektorkvaterni is.) A skkvaternik vals rsze a sk origtl mrt negatv tvolsga, kpzetes vektor rszk pedig a sk normlis egysgvektora. A kvaterni ilyen normlsa azt biztostja, hogy a sk normlvektora az origtl kifel mutat. A trkvaternik, illetve pontkvaternik esetn az azonos vals rszeket tekinthetjk egy vilghoz tartozknak (ha a vals tengely az id, egyazon pillanathoz tartozknak). Ezeknek a kvaterniknak a kpzetes rszvel a szoksos vektormveleteket vgezhetjk el. Az ugyanazon hromdimenzis trhez tartoz vektorok kvaterniit (amelyek teht azonos vals rszek) a forgatsi transzformci sem vlasztja el egymstl, hiszen vals rszk a forgats utn is ugyanaz marad. Belttuk azt is, hogy a forgat transzformci elvgzse sorn az elforgatott kvaterni vals rsze nem befolysolja az eredmny kpzetes rszt, az elforgatott vektort. A trbeli pozci lersra szolgl homogn koordinkat ebben az anyagban mindig az 1 kiegszt koordintval troljuk a kvaternikban. A homogn koordints hromdimenzis teret ezrt nem a kvaterni orighoz helyezve, hanem a vals 1 egysghez (Base0-hoz) eltolva mutatjuk. Ennek az eltolt hromdimenzis trnek a koordintatengelyeit rajzainkon vkony piros vonallal tntetjk fel. (Persze, a rajzon brzolt skok esetn is a fentiekben mondott origtl mrt tvolsg alatt ilyenkor a Base0-tl mrt tvolsgot rtjk.) Ebbl az eltolt trbl kilgnnak az idelis pontok, amelyeknek 0 a kiegszt homogn koordintjuk, de ezeket gysem tudnnk a hromdimenzis, vges tereink kpn megmutatni. (Nagyon szerencss viszont, hogy az tengely, tengely s a tengely idelis vgtelen tvoli pontjnak kvaternija ppen BaseI, BaseJ s BaseK-val egyezik meg.) Az anyag els sszelltsa sorn a perspektivikus lekpezs tanulmnyozsakor dbbentem r arra, hogy a tr pontjaihoz rendelhet homogn koordintk trolsra ppen ngy helyre van szksg! A kiegszt, negyedik koordintt el lehet helyezni egy kvaterni vals rszben is! Ezrt az anyagot

129

Kvaternik s alkalmazsuk
teljesen tdolgoztam. Kt j fejezetet is beptettem a dolgozatba. Lnyeges vltoztatsokat hajtottam vgre a Kvaterni_mveletek modulon is: a vgtelen rtkek kezelsre a homogn koordintarendszer idelis pontjainak megfelelen j tulajdonsgokat, metdusokat, konstruktorokat ksztettem, tovbb beptettem a vektor s a kvaterni osztlyhoz egyenlsget vizsgl relcikat, illetve fggvnyeket, vgl programoztam a ngydimenzis skalris s a ngydimenzis vektorilis szorzs fggynyt is. Kibvtettem a Kvaternis_szerkesztsek modult is, ugyanis tbb fggvnynek elksztettem azt a vltozatt is, amely a homogn koordints kvaternikon alapul. Volt, ahol javtanom kellett. Machanikusan nem lehetett minden kvaterni 0 vals rtkt 1-re cserlni. Pldul a hromdimenzis trbeli kzppontos tkrzst kvaterni origra vett tkrzssel lehetett (br elvileg hibsan, de j eredmnyt adan) programozni, most csak a kvaterni vektor rszvel vgzem el a tkrzst (ez brhov eltolt hromdimenzis tr esetn is jl mkdik). A forgatsokkal nincsen problma. Fltem volna egy olyan vltoztatstl, amikor kvaternik vals rszbe nknyesen 1-et runk, ha nem mutattam volna ki korbban, hogy a vals rsz rtke nem vltozik a forgatsi transzformci sorn, valamint, hogy a vals rsz rtke a forgatsnl nem hat a kpzetes rszre. Msrszt a forgats tengelye pldul sk esetn az origbl a Near pontba mutatott (irnya a sk normlvektornak irnya volt). Most ez csak annyiban mdosult, hogy az orig helyett Base0 ponton megy t a tengely, s a sk Near pontja esetn is a kvaterni vals rsznek rtke 1. A homogn koordintk trolsra a kvaterni kivlan alkalmas. A kvaterni vals s kpzetes rsznek megklnbztetse is jl illik a homogn koordintk kiegszt s valdi rsznek elklntsre. A sk homogn koordints ngydimenzis egytthatvektora, a skkvaterni pedig a kvaterni rszek szerinti felbontsban is teljesen rtelmes: a vals rsz a sk Base0-tl mrt tvolsga, a kpzetes rsz a sk normlis egysgvektora. A trbeli szerkesztsek elvgzsre kellemesen hasznlhat eszkzt nyertnk. A kvaternikban a pontokat mindig homogn koordintkkal trolhatjuk. Az egyeneseket egy pont s egy nyjtottzsugortott, tkrztt irnyvektor kettseknt kezelhetjk. A skoknl pedig homogn koordints s Plane objektumos alakjuk kztt lavrozhatunk aszerint, hogy mikor milyen kezelsre van szksg. A ngydimenzis homogn koordints szorzsokkal kzenfekv a hrom pontra illeszked sk, illetve a hrom sk metszspontjnak meghatrozsa, de nagyon egyszer annak vizsglata is, hogy egy pont illeszkedik-e egy skra, illetve annak szmtsa, hogy milyen tvol van egy pont egy sktl. A trbeli forgatst el lehet vgeztetni vektorok s mtrixok segtsgvel is. Viszont a kvaternival megvalstott forgatshoz kevesebb adat meghatrozsra s trolsra van szksg, s a forgat kvaterni ellltsa, valamint a forgats vgrehajtsa is egyszerbb. (Ebben az anyagban csupn utaluk arra, hogy a transzformcis mtrix a forgats elvgzsre a kvaterni konkurense, homogn koordintk alkalmazsa pedig a transzformcis mtrix egysgesebb hasznlatt eredmnyezheti.) Budapest, 2013. februr 5. (Vissza a #TARTALOMra )

130

Az elektronikus knyv kiadja a Kossuth Kiad. Felels kiad Kocsis Andrs Sndor Az elektronikus knyv szerzi s kiadi jogvdelem alatt ll. Illetktelen msolsa, reproduklsa, mdostsa a szerz s a kiad rsbeli hozzjrulsa nlkl tilos. Az elektronikus kiadshoz fzd minden jog fenntartva. Ormai Lrnt 2012 Kossuth Kiad 2012 ISBN 978-963-09-7458-5 Az elektronikus kiadsban kzremkdtt Grb Krisztin, Pek Zsolt Projektvezet Fldes Lszl www.multimediaplaza.com www.kossuth.hu

Anda mungkin juga menyukai