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
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:
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). ( ( ( ) ( ) ( ) ) ( ) ( ( ) ( ) ) ( ) )
( ( (
) ) )
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 termszetesen akkor is teljesl, ha a kvaternit s ): ( ) nmagval (vagy a konjugltjval) szorozzuk (
akkor az eredmny vals, hiszen az albbi szorzsi eredmny zrjelezett, msodik rsze : ( )
Csak megjegyezzk, hogy egy kvaterninak s a konjugltjnak az sszege is vals: ( A vals szmok ( ) ( )
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: | | | | | | | | |
akkor mivel a zrjelen belli rsz egysg kvaterni ( ezrt tallhat olyan | | ) ( || ) | | ( amelyre )
szg,
Kvaternik s alkalmazsuk
|| | |
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 ): ( ) ( )
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
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 ( )
Kvaternik s alkalmazsuk
A konjuglst a kvaternin vgzett egyszer algebrai mveletekkel is lerhatjuk. Ehhez a
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:
-t, eszerint:
10
Kvaternik s alkalmazsuk
Ebbl a
Az els egyenletet
| |
| |
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:
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
Ezek szorzata: ( ) ( )
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.)
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:
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 ( )
tengely krli
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 ) ( ) ) ( ) ( ) ))
Hasonlkppen a jobb oldali kt tnyez szorzatra alkalmazva: ( ( ) ) ( ( ) szg elforgatst jelent: ( ) ( ) , akkor a )
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: ( ) ( ) ( )
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: ( )
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 ) ( ) ( )
A prhuzamos sszetev vltozatlan marad, a merleges sszetev Pldul a korbbi forgatsi pldnkban ( ) ( )
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):
( Az ( ) ( ) ( ( (( ) ) ) szorzat a )
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
( )
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. )
Az els kett sszeszorzst nem kell jra elvgeznnk, elg a #Kvaternik_szorzsi_szablya alapjn szorzatukat idemsolnunk (a harmadik szorzs mg csak kijellve): ( ) ( )
( ) (
( )
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: ( )
( ) ( )
( ) ( ( )
) )
( ( Ekkor )
( ( ( || ) )
|| ) (
) ( )
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: ( ) ( )
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
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 ): ( )
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
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 =
// 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) // // // // //
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
) ) ) )
// 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
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 && && && &&
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
) ) ) ) ) )
// 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
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 )
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)
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
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 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
// 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) )
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
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
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 krlrt krnek kzppontja a cscsoktl egyenl ( ) tvolsgra van. Ezt is meghatrozhatjuk ismeretben az elz oldali bra alapjn: ( ) ( ) ( ) : ( ) ( )
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 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.)
( 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
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
// 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
// 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
* * * *
* * * *
// 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
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,
) ) ) )
// 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
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
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 ( )
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
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