Nevíte-li si rady s jakýmkoliv matematickým problémem, toto místo je pro vás jako dělané.
Nástěnka
❗22. 8. 2021 (L) Přecházíme zpět na doménu forum.matweb.cz!
❗04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
❗23.10.2013 (Jel.) Zkuste před zadáním dotazu použít některý z online-nástrojů, konzultovat použití můžete v sekci CAS.
Nejste přihlášen(a). Přihlásit
Stránky: 1
Jelena: Edit - kolega řeší Sledování paprsků (objekty - koule bez problému, rovina potíž). Podrobně - příspěvek 15.
Předávám do laskavé péče, děkuji :-)
Dobrý den,
potřeboval bych poradit s výpočtem roviny a přímky.
Mám vstupní vektor A (x, y, z)
Mám 4 body roviny - každý bod má X, Y, Z.
Jak vypočítám zdali se vektor A protíná s rovinou?
(Jde jen o to, zdali ji protíná, NEpotřebuji vypočítat kde)
Tento problém bych chtěl řešit později programově.
Offline
Ahoj,
protnou se právě tehdy, když vektor A nebude kolmý k normálovému vektoru roviny, tj. jejich skalární součin bude nenulový. Normálový vektor spočteš snadno pomocí vektorového součinu (stačí 3 body v rovině) - např. pokud mám body P, Q, R v rovině, tak norm. vektor bude (R-P)x(R-Q).
PS. Programově tento problém podle mě nemá smysl řešit, protože v počítačové aritmetice nejsme schopni přesně určit rovnoběžnost.
Offline
↑ Bati:
Děkuji za odpověď.
Na internetu je napsáno, že rovina v prostoru má nekonečně mnoho normálových vektorů.
Konrétně na foru zde: http://forum.matweb.cz/viewtopic.php?id=16973
Stačí když tedy spočítám jeden z nekonečna a porovnám je?
Edit: nevím jaký to má smysl, ale dělám program TZV ray tracer, kdy posílám ,,paprsky,, a zkoumám zdali se tento paprsek protne s rovinou, v tom případě to nějaký smysl mít musí, nebo ne?
Offline
↑ PanTau:
To je dáno tím, že může být libovolně velký, ale nám jde pouze o jeho směr a ten je samozřejmě jednoznačný.
V takovém programu můžeme s jistotou zjistit pouze případ, kdy se protnou. Není ale možné tvrdit, že jsou rovnoběžné, protože výpočet na počítači je vždy nepřesný.
Z praktického hlediska: Pokud budu mít rovinu a vyšlu paprsek, tak se s rovinou vždy protne (pokud bude ta rovina dostatečně velká).
Offline
Takže pokud bych to chtěl vypočítat jako ukázkový příklad:
Vektor A = A(0,0,0)
Rovina bude mít čtyři body (P, Q, R, S)
P = P(1,1,1)
Q = Q(2,1,1)
R = R(2,2,1)
S = S(2,1,1)
Stačí mi vzít body P,Q,R a vypočítat ((R-P)x(R-Q))
u: R-P = 1,1,0
v: R-Q = 0,1,0
vysledny: u x v = 1*0 - 1*0 , 0*0 - 0*1 , 1*1 - 0*1
vysledny: (0,0,1)
Skalární součin A * vysledny = 0, 0, 0
Tudíž skalární součin je nulový tudíž neprotne?
Offline
Zdravím,
jen poznámky - vektor máš nulový Vektor A = A(0,0,0), to asi nepoužiješ na nic. Potom musíš mít jistotu, že 4. bod je ve stejné rovině, jako předchozí 3 body, ze kterých je rovina - to kontroluješ?
Jinak buď použitím vektorového součinu (jak děláš), nebo z bodů sestavit předpis roviny (v obecném tvaru) a porovnat normálový vektor roviny s Tvým zadaným. A ještě jinak - děkuji za hlášení :-)
Offline
↑ jelena:
Hezký večer, nic nekotroluji, vůbec tomu nerozumím. Pokoušel jsem se počítat nějaký příklady ale stále mi to nevychází.
Byl by někdo tak hodný a demonstroval to na příkladě.
Je jedno jakým způsobem.
Edit: není zač, bylo to slušností, zatím se nikdo neozval :-)
Offline
↑ PanTau:
nech si Tvůj příklad, jak je, a jen změň vektor (jelikož ten Tvůj nulový nemůže nic protnout ze své podstaty).
Vektor A_1 = A(0,0,4) a jiný vektor na kontrolu A_2 = A(2,2,0). Zbytek použijeme stejně (i když jsem nekontrolovala.
Rovina bude mít čtyři body (P, Q, R, S)
P = P(1,1,1)
Q = Q(2,1,1)
R = R(2,2,1)
S = S(2,1,1)
Stačí mi vzít body P,Q,R a vypočítat ((R-P)x(R-Q))
u: R-P = 1,1,0
v: R-Q = 0,1,0
vysledny: u x v = 1*0 - 1*0 , 0*0 - 0*1 , 1*1 - 0*1
vysledny: (0,0,1)
Který "vektor" protne a který ne? (ono úplně dobře není povídat, že "protne vektor" - protne přímka, pro kterou je tento vektor směrový).
Ohledně 4 bodů - 3 body tvoří jednu rovinu, pokud nejsou na stejné přímce. Další ze zadaných bodů nemusí v rovině ležet - to je třeba kontrolovat (nebo mít jistotu, že máš 4 body z jedné roviny), jinak bys totiž neměl jen jednu rovinu.
Offline
↑ jelena:
Po tom opět:
(R-P)x(R-Q)
( u )x( v ) - označení
u = (1, 1, 0)
v = (0, 1, 0)
( u )x( v ) = 1*0-1*0, 0*0 - 0*1, 1*1 - 0*1
( u )x( v ) = 0, 0, 1 = vysledny
Skalární součin:
A_1:
vysledny * A_1 = 0*0+0*0+1*4 = 4 (PROTNE)
A_2:
vysledny A_2 = 0*2+ 0*2+ 1*0=0 (NEPROTNE)
Je tomu tak? Děkuji
Offline
↑ PanTau:
Zdravím,
pokud jsem nepřehlédla něco ve výpočtech, tak postup bych měla stejný (ještě odkaz na metodu). Jinak - až budeš testovat, tak na úvod je dobré si zvolit roviny, co přesně představuješ (např. stěny krychle nebo jehlanu) a k tomu dobře představitelné vektory přímek (kolmé těmto stěnám nebo rovnoběžné).
Jak budeš posuzovat paprsek, který v rovině leží? Děkuji za upřesnění.
Offline
↑ jelena:
Děkuji za odkaz.
Metodu jsem implementoval programově a nějak nefunguje :-)
Asi nad tím budu muset trávit další noci, hihi.
Jen tak pro zajímavost:
Offline
↑ PanTau:
:-) zcela vůbec nefunguje? Pokud se Tebe neujme některý hodný kolega, tak se zkusím podívat nejspíš zítra odpoledne, dřív těžko. Kolegům děkuji.
Jinak paprsek(na jednoduchém ilustračním obrázku) je určen směrem(vektor) a počátkem(vektor)
počátek by měl být bod, ne vektor - jak jsi to zadával (ale to také až zítra)? Děkuji.
Offline
↑ jelena:
Zdravím, paprsek obsahuje 2 vektory - z vektoru se dá udělat snadno bod., ne?.
Jinak funguje tak jako že funguje ale špatně. :-)
Viz: výsledek programu:
Okno A obdélník v 3D který má být pomocí ,,paprsků" převeden do B - SNEHULAKA SE NEVŠÍMEJ TE :-) - barvy take ne.
Jinak to funguje tak, že projíždím každý PX 3D scény a kontroluji zdali tam leží "kus" obdélníku, pokud ano, označím to barvou(a tím se jako vykreslí).
Stejnou metodu jsem udělal pro sněhuláka(tedy koule) a ta funguje, jen ten obdélník zlobí.
Offline
↑ PanTau:
Také pozdrav,
paprsek obsahuje 2 vektory - z vektoru se dá udělat snadno bod., ne?.
:-) mám dojem, že jsem to dosud nezkoušela. Vlož, prosím, popis jednoho paprsku - jak je zadán a co to představuje prakticky.
Pokud rozumím dobře, tak děláš něco takového a sněhulák "prosledovat" šel (i když je to složitá plocha), ale rovina prosledovat nejde. Mám rozumět, že chceš prosledovat šedou rovinu nalevo a převést do do obdélníku v červeném rámečku napravo? Nebo jinak?
I když tak nebo jinak - nedaří projít celou rovinu (přesně nějakou vymezenou část) - když zachytíš vrcholy vymezeného obdélníku - to se také nedaří? Co to dělá, když (ne)funguje?
Kolega Bati v tom něco spatřuje? Děkuji.
Offline
Ano, přesně tak raytracing(Sledování paprsku)
Převádím z 3D scéna (OBRÁZEK A) do OBRÁZKU B(červený).
Převádím jednoduchá geometrická primitiva koule a rovinu.
Převod koule proběhl v pořádku(podařilo se mi definovat rovnice/výpočty a funguje to), problém je pouze v rovině (A TO SE ZDÁ BÝT JEDNODUŠŠÍ :-) )
Jak to funguje...
V prostoru(OBRÁZEK A) mám pozorovatele(tedy to odkud koukám - mám vektor KDE JSEM a vektor KAM koukám).
V prostoru je dále list těles(seznam těles) - NYNÍ se věnujme jen rovině => mám jedno těleso ROVINU, která je popsána 4 vrcholy(A,B,C,D), kdy každý vrchol má souřadnice x,y,z kdy souřadnice z je vždy 0 (tedy stejná), liší se tedy pouze v x a y.
Převod z prostoru do obrázku( OBRÁZEK B )
Probíhá tak, že projíždím každý PX obrázku v cyklu.
Paprsek je definován 2 vektory, vektor origin - počátek paprsku a vektor direction - směr paprsku.
Pro výpočet je potřeba provádět transformace.
Tudíž:
//////////////////////// PŘEPOČTY OKNA NEZAJÍMAVÁ ČAST
float fovy = mS.DMax; // jak daleko vidím ve 3D scéně
Ray ray = new Ray(position); // založím si nový paprsek,
float height = (float)(2 * Math.Tan((Math.PI / 180f) * (fovy / 2f))); // přepočítám výšku obrázku
float width = ((float)window.Resolution.Width / (float)window.Resolution.Height) * height; // přepočítám šířku okna
Vector3f rightUpCorner = direction + (height * 0.5f) * up - (width * 0.5f) * strana;
float differenceX = width / (float)window.Resolution.Width;
float differenceY = height / (float)window.Resolution.Height;
Vector3f stepRight = differenceX * strana;
Vector3f stepUp = differenceY * up;
Vector3f transUp = new Vector3f(0, 0, 0);
///////////////////////////////// KONEC PŘEPOČTů
for (int i = 0; i < window.Resolution.Height; i++){ // výška obrázku
transUp = i * stepUp;
for (int j = 0; j < window.Resolution.Width; j++){ //šířka obrázku
ray.direction = rightUpCorner + j * stepRight - transUp;
ray.direction.Normalize();
// kontroluj zdali se paprsek protne
bool hit = listOfMyrectangleInThePlane[0].RayPlane(ray.direction, listOfMyrectangleInThePlane[0]);
if (hit)
{
window.SetPixel(i, j, aktivniColor); // paprsek se protnul s objektem nastavuji aktivni barvu
}
else
{
window.SetPixel(i, j, neaktivniPozadiBarva); // paprsek se neprotnul nastavuji neaktivni barvu
}
}
}
Kdy paprsek kontroluji pomocí výpočtu(který jsme dali dohromady spolu tady(výše ve vlákně dotazu)
float z = 0.0f;
Vector3f P, Q, R;
P = new Vector3f(mritp.xMin, mritp.yMin, z); //mript je pouze objekt tudíž bereme xMin objektu a yMin objektu
Q = new Vector3f(mritp.xMax, mritp.yMin, z);
R = new Vector3f(mritp.xMax, mritp.yMax, z);
Vector3f u = R - P;
Vector3f v = R - Q;
Vector3f cross = Vector3f.Cross(u, v);
float dot = Vector3f.Dot(directionVectorRay, cross);
float EPSILON = 0.0000000000000000001f;
if (dot < EPSILON)
return false;
else
return true;
Doufám že se nezlobíte že jsem vložil zdrojový kód, přišlo mi to jako nejlepší řešení pro demonstraci a popsání problému, doufám že kódu je rozumět (důležité kroky jsem popsal komentářem).
Vector3f je pouze programová definice vektoru.
Offline
↑ PanTau:
:-) tak řeknu, že problém je již dostatečně rozpracován, aby byl přesunut do AaP (ještě upravím úvodní příspěvek). Navíc někde musí být určitě hotový kód. Není mi ale jasné, proč šlo prohlížet sněhuláka (technika by měla být stejná, že paprskem narazím na kousek sféry).
Zde tedy máme plochu - rovinu xOy, na ploše je vymezen obdélník (vrcholy ABCD), pozorovatel je zadán vektor origin (to není vektor, ale bod-počátek) - počátek paprsku a vektor direction - směr paprsku, tedy paprsek je zadán jako přímka v parametrickém tvaru.
Pro upřesnění - body P, Q, R - jsou na původní rovině (tedy náleží obdélníku ABCD)?
Pozorovatel (paprsek) vždy vychází ze stejného počátečního bodu a pouze mění směr? Umí dohlédnout na vrcholy A, B, C, D? Kde je směrový vektor pozorovatele?
Mám totiž dojem, že vysíláš paprsky rovnoběžně (ne z jednoho zdroje) a mají možnost protnout rovinu jako takovou, ale neověřuješ, že jsou ve vymezeném obdélníku.
Tak přesouvám a zdárné dokončení přeji.
Offline
Ahoj, nevím čím to bylo, ale problém jsem vyřešil. Navštívil jsem kamaráda a ten mi poradil jiný postup.
Díky
Offline
↑ PanTau:
V programovém kódu v příspěvku #11 je zásadní chyba, neuvědomil sis, že skalární součin může být i záporný. Tj. podmínka dot < EPSILON je spnlěna např. i pro dot= -1000, což se od nuly liší hodně. Co ve skutečnosti potřebuješ testovat je |dot| < EPSILON.
Navíc je dobré si uvědomit, že velikost skalárního součinu závisí na velikostech vektorů, a proto to porovnání tak jak je není moc objektivní (teoreticky, kdybych vzal 2 vektory, které to vyhodnotí jako kolmé a dostatečně je prodloužil, tak je to pak vyhodnotí jako nekolmé). Z tohoto důvodu bych to nějak přenormoval.
Dále jsem vaší diskuzi moc nesledoval, ale zdá se mi, že tyto fakty, které jsem zmínil, tu ještě nepadly.
Offline
Stránky: 1