Portál AbcLinuxu, 1. května 2025 22:40

Průsečík dvou úseček

28.3.2009 22:40 | Přečteno: 12548× | Jiné | poslední úprava: 29.3.2009 13:49

Dělal jsem úkol z programování, ale nějak špatně to funguje.

Mám 2 úsečky, každá je zadaná dvěma body. Mám zjistit jestli jsou rovnoběžné, různoběžné, kolmé, jestli leží na jedné přímce a v tomto případě jestli se nepřekrývají. Pokud mají průsečík, vypsat ho.

Vyřešil jsem to nějak takto:

A právě ve zjišťování, zda je bod na úsečce je zakopaný pes. Zjišťuji to takto:

Problém ale je, že např. při hodnotách AB = {{0,0}, {2,2}} a CD = {{0,2},{3,-3}} dostanu, že bod na úsečce neleží, protože
2.82842712474619029094924371747765690088270947265625 není to samé jako
2.82842712474918984686003386741504073143005371093750

Tak co teď s tím? Jak jinak zjistit, jestli tam ten bod leží nebo ne?

Update

Dá se tohle ještě zkrátit?
       

Hodnocení: 36 %

        špatnédobré        

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

Komentáře

Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře. , Tisk

Vložit další komentář

Sleep_Walker avatar 28.3.2009 22:56 Sleep_Walker
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Odpovědět | Sbalit | Link | Blokovat | Admin
A[xa,ya], B[xb,yb], usecka AB lezi na primce s rovnici y=ax+b

lezi bod X[xx,yx] na usecce AB?

aby lezel na usecce, musi splnovat 2 podminky:

a) lezet na prislusne primce - overis, zda plati rovnost po dosazeni souradnic do y=ax+b

b) X lezi "mezi" A a B - otestujes, zda min(xa,xb) < xx < max(xa,xb) && min(ya,yb) < yy < max(ya,yb)

pokud splnuje obe podminky, lezi na usecce. Timto se vyhnes velkym cislum.

Ber to jako odpoved na otazku. Zbytek nekomentuji :)
Jardík avatar 28.3.2009 23:24 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Super, a teď je problém zase jinde a sice ve směrnici, kterou to nevypočítá přesně a tak nedostanu rovnost pro rovnici přímky :-( Neporadí někdo, jak to všechno udělat bez toho nepřesného dělení? Nebo nějakou rychlou třídu "zlomek" :-)
Věřím v jednoho Boha.
29.3.2009 00:50 Let_Me_Be | skóre: 20 | blog: cat /proc/idea/current | Brno
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Neni nic jako nepresne deleni. Problem je v reprezentaci realnych cisel v pocitaci.

Je docela smutne, ze misto zrejme odpovedi se zde objevuji naprosto nesmyslne rady.

V zadnem programu by se nemelo za zadnych okolnosti objevit porovnavani hodnot typu float/double/long double na (ne)rovnost. To je cely problem.
Linked in profil - Můj web - Nemůžete vyhrát hádku s blbcem. Nejdřív vás stáhne na svoji úroveň a pak ubije zkušenostmi.
29.3.2009 01:07 Vin
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

Tak neděl, ale násob - test rovnosti ("rovnici") k_AB == k_CD můžeš vyjádřit jako (y_B - y_A)/(x_B - x_A) == (y_D - y_C)/(x_D - x_C), což je ekvivalentní (y_B - y_A)*(x_D - x_C)  == (y_D - y_C)*(x_B - x_A) (což je ekvivalentní nulovému skalárnímu součinu normály prvního vektoru a druhého vektoru, jak jsem poznamenal v odpovědi Platonixovi)

Ovšem, také záleží, co máš na vstupu.

Jardík avatar 29.3.2009 15:02 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Na vstupu mám 2 body pro každou úsečku.

Tak jsem to upravil, většinu dělení převedl na násobení. Už to projde s {{0,0},{2,2}},{{0,2},{3,-3}}, ale zase mi to neprojde testem na progtestu s hodnotami {{4,7},{12,8}},{{5,11},{40,-300}}, protože to nepřesně počítá x-ovou a y-ovou souřadnici průsečíku, protože tam se mi dělelní nepodařilo zbavit.
Věřím v jednoho Boha.
Josef Kufner avatar 29.3.2009 17:19 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Nejde o dělení ani o násobení. Jde o reprezentaci čísla jako takového. 0,1 prostě nemá v binární soustavě ukončený desetiný rozvoj a spousta dalších čísel také ne.

Výpočty s plovoucí desetinou čárkou se dělají tak, že omezíš počet operací při kterých vznikají největší chyby nebo je přepíšeš tak, aby chyba byla co nejmenší (sčítat/odčítat srovnatelně veliká čísla, násobit/dělit co nejméně a pokud možno už nepočítat s výsledky násobení či dělení, aby se chyby nesčítaly).

Porovnávání uďeláš odečtením a porovnáš zda je absolutní hodnota výsledku menší než požadovaná tolerance. Tedy místo A == B uděláš abs(A - B) < epsilon, kde epsilon je např. 1E-10.
Hello world ! Segmentation fault (core dumped)
29.3.2009 18:28 Let_Me_Be | skóre: 20 | blog: cat /proc/idea/current | Brno
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Vzdej to, on je proste blbej. Uz to mu to sem napsalo nekolik lidi.
Linked in profil - Můj web - Nemůžete vyhrát hádku s blbcem. Nejdřív vás stáhne na svoji úroveň a pak ubije zkušenostmi.
29.3.2009 01:33 deda.jabko | skóre: 23 | blog: blog co se jmenuje "každý den jinak" | za new york city dvakrát doleva a pak už se doptáte
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
spatne zvladnuta analyza...

vybral sis blbou reprezentaci usecky pro dany jazyk... takze doporucuji vymenit jednu vec z toho...

bud zustanes u jazyka a pouzijes lepsi reprezentaci, ktera netrpi tak vyraznymi neduhy...

nebo pouzijes nejaky normalni jazyk, ktery zvlada pocitani s racionalnimi cisly a muzes zustat u parametrickeho vyjadreni primky.
Asi před rokem se dostali hackeři na servry Debianu a ukradli jim zdrojové kódy.
Jardík avatar 29.3.2009 03:34 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Co je to analýza? :-)
Věřím v jednoho Boha.
Josef Kufner avatar 29.3.2009 17:21 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Rozbor zadání a případně i zevrubný návrh klíčových komponent a datových typů. (V tomto kontextu.)
Hello world ! Segmentation fault (core dumped)
Sleep_Walker avatar 29.3.2009 10:44 Sleep_Walker
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Uf, mas recht, tohle mi nedoslo. Mel bych si odpoved vice rozmyslet.
hikikomori82 avatar 28.3.2009 23:05 hikikomori82 | skóre: 18 | blog: foobar | Košice
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Odpovědět | Sbalit | Link | Blokovat | Admin
const DELTA = 0.000001 - definovana presnost

if abs(k1-k2) < DELTA then ... k1 a k2 su v ramci danej presnosti rovnake
Slobodný font na technické kreslenie
29.3.2009 15:50 AHAHA | skóre: 7 | blog: ZZZ
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

Neni to sice idealni reseni, ale rozhodne nejjednodussi a v realnych aplikacich je to asi uplne jedno.

Jen je potreba zvolit vhodny odstup delty a presnosti reprezentace realneho cisla v zavislosti na poctu operaci, aby chyba nikdy nepresahla velikost delty.

29.3.2009 16:53 peterh
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

Toto je standardne riesenie ktore sa uci aj na numerickej matematike, proste sa treba zmierit s konecnou presnoustou cisel s poh. rad. ciarkou. Ked to chces presne tak to rataj symbolicky cez zlomky..

29.3.2009 00:00 Platonix | skóre: 20 | blog: FUD: Férový Uživatelův Deníček
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Odpovědět | Sbalit | Link | Blokovat | Admin

Nebylo by jednodušší napočítat směrové vektory obou úseček (to pomocí rozdílu souřadnicí jejich bodů). Potom stačí provést skalární součin těchto vektorů. Je-li roven nule, jsou kolmé, je-li roven 1 jsou rovnoběžné. Je-li něco mezi, tak jsou obecně různoběžné.

Když já tomu prostě nerozumím. Kdo si neváží svobody, je na půli cesty o ni přijít
29.3.2009 00:30 Vin
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

 

je-li roven 1 jsou rovnoběžné.

Co třeba (1,1) a (-1,-1)? Ne, tohle by se testovalo přes normálový vektor - pokud je normálový vektor prvního vektoru kolmý na druhý vektor (tedy skalární součin druhého vektoru a normály prvního je roven nule). Normálový vektor (a,b) = (-b,a)

 

Ale jinak dobrý - už jsem chtěl v předešlém vlákně odpovědět, jak řešit situaci se zlomky - tohle je o poznání elegantnější.

29.3.2009 00:44 Vin
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

I když - je to vlastně to samý, co jsem chtěl navrhnout, jenom jinak vyjádřený.

29.3.2009 00:53 Platonix | skóre: 20 | blog: FUD: Férový Uživatelův Deníček
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

Není třeba testovat přes normálový vektor. Skačí, když malinko opravím ten svůj návrh: bude se počítat absolutní hodnota skalárního součinu. Jo jinak je samozřejmě třeba vektory normovat!

Tedy celý vzoreček by byl asi takovýto:

1. najdu směrové vektory pomocí rozdílu souřadnic obou bodů

2. spočítám výraz: (skalární součin 1 a 2 vektoru)^2/((skalární součin 1 a 1 vektoru)^2*(skalární součin 2 a 2 vektoru)^2)

3. je-li výsledek 1 - rovnoběžné, 0 - kolmé, něco mezi jsou obecně různoběžné svírají úhel = acos(sqrt(výsledek))

Když já tomu prostě nerozumím. Kdo si neváží svobody, je na půli cesty o ni přijít
29.3.2009 00:56 Vin
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

No, ale těm operacím bych se radši vyhnul - narůstá časová složitost a dochází k nepřesnostem (normála je levná).

29.3.2009 01:12 Platonix | skóre: 20 | blog: FUD: Férový Uživatelův Deníček
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

Nevím, co je na normále tak super. Samozřejmě musíš ty vědět, jaké funkce má ten program poskytovat. Já navrhuji řešení, které je robustní (neselže při vyšším počtu rozměrů) a je naprosto standardní (opírá se o definice skalárního součinu a příslušné věty). Alternativně můžeš na 0 testovat skalární součin obou vektorů a zároveň jednoho vektoru a normálového k druhému. Přijde mi to ale zbytečné, když se vše dá ošetřit jedním vzorečkem.

Když já tomu prostě nerozumím. Kdo si neváží svobody, je na půli cesty o ni přijít
30.3.2009 09:23 droid
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

Časová složitost je stejná.

29.3.2009 00:55 Platonix | skóre: 20 | blog: FUD: Férový Uživatelův Deníček
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

Jo a nedoporučuji normálový vektor používat protože pro více dimenzí je problém s jeho definicí (je nejednoznačný). Např.: Jaký bude normálový vektor k vektoru (1,1,1). Je to totiž celá normálová rovina.

Když já tomu prostě nerozumím. Kdo si neváží svobody, je na půli cesty o ni přijít
29.3.2009 00:57 Vin
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

To ale není tenhle případ.

default avatar 29.3.2009 01:09 default | skóre: 22 | Madrid
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Odpovědět | Sbalit | Link | Blokovat | Admin

Ty vole! Tyhle problémy bych chtěl mít! :-D

29.3.2009 20:39 rastos | skóre: 63 | blog: rastos
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Náhodou s týmto problémom sa potýkam pomerne často (v jednom nemenovanom CAD systéme). Predstav si, že potrebuješ spraviť union alebo prienik dvoch polygónov, z ktorých každý môže mať stovky až tisícku hrán. A prípadne tých polygónov môže byť stovka a potrebuješ bleskovo vedieť či sa niektoré z nich prekrývajú alebo nie. Bleskovo znamená - v obsluhe eventu na pohyb myši. Ľudia, ktorí tieto problémy majú a dokážu ich riešiť, sú celkom dobre platení.
30.3.2009 12:36 David Jaša | skóre: 44 | blog: Dejvův blog
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Což díky moorovu zákonu a neoptimalizovanosti "běžných" programů vede k paradoxním situacím, kdy i tyto šílenosti proběhnou rychleji, než vykreslení tabulky v OpenOffice...
Jardík avatar 29.3.2009 03:53 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Odpovědět | Sbalit | Link | Blokovat | Admin
Mně už to nepřemejšlí, jde tohle nějak zkrátit?
    (By - Ay)(CyDx - CxDy) - (Dy - Cy)(AyBx - AxBy)
y = ---------------------------------------------
        (By - Ay)(Dx - Cx) - (Dy - Cy)(Bx - Ax)
Věřím v jednoho Boha.
Saljack avatar 29.3.2009 10:52 Saljack | skóre: 28 | blog: Saljack | Praha
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Odpovědět | Sbalit | Link | Blokovat | Admin
Tak nastav řád, při kterém už je to zanedbatelné.
Sex, Drugs & Rock´n Roll.
Jardík avatar 29.3.2009 18:38 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Odpovědět | Sbalit | Link | Blokovat | Admin
Příloha:
Tak jsem to nějak spatlal dohromaci, dělení jsem omezil jak jen to šlo. S ukázkovými hodnotami, co jsou na progtestu mi to projde, ale přesto mi progtest dal jen 3.6 ze 4, že prý tam byla 90.91 úspěšnost při "Extenzivní test náhodnými vstupy". Můžete na to někdo kouknout, co tam mám špatně? Prosím ...
Věřím v jednoho Boha.
Jardík avatar 29.3.2009 19:52 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
To mě teda poserte, udělal jsem to znovu se směrnicema, napsal jsem si třídu "zlome", jelikož jsou na vstupu jen celá čísla, a ten šmejd mi pořád nechce dát 4b a ještě mi hlásí, že to neprošlo kompilátorem s parametrem -pedantic, přitom u mě to s ním projde, všechno určitě funguje, jak má. To musej mít nějaký rozbitý.
Věřím v jednoho Boha.
Jardík avatar 29.3.2009 19:53 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Příloha:
Tady to je
Věřím v jednoho Boha.
Jardík avatar 29.3.2009 21:39 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
zlome = zlomek
Věřím v jednoho Boha.
28.9.2009 14:54 morph
Rozbalit Rozbalit vše Re: Průsečík dvou úseček

 Nevim proc presne to neproslo tobe, ale v tom modu -pedantic si to zkus nejdriv zkompilovat na progtestu v sekci prekladace. Muze ti to na tvym systemu hazet jiny warningy nez u nich a uz to neprojde..

29.3.2009 22:42 David Jaša | skóre: 44 | blog: Dejvův blog
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Odpovědět | Sbalit | Link | Blokovat | Admin
Z bodů zjistím k a q pro rovnici přímky y = kx + q
Tímto tvarem rovnice nejsi schopen popsat přímky rovnoběžné s osou y - ty chyby by mohly být pokusy počítače o dělení různých čísel nulou (ale nejsem programátor, takže netuším, jestli je to správný výklad). Blbuvzdorný tvar rovnice přímky v rovině je:  ax + by +c = 0 , kde "a" a "b" jsou pořadnice normálového vektoru k úsečce a c je konstanta, která se dopočítá dosazením souřadnic bodu ležícího na přímce za "x" a "y".

Ve tří- a vícerozměrném prostoru ti pak nezbyde, než přímky vyjadřovat parametrickými rovnicemi {x}T = {a}T + {b}T, kde vektor "x" jsou souřadnice libovolného bodu na přímce, vektor "a" souřadnice známého bodu ležícího na přímce, vektor "b" souřadnice směrového vektoru přímky a "t" je parametr.
oVirt | SPICE
29.3.2009 22:49 David Jaša | skóre: 44 | blog: Dejvův blog
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
PS: překvapuje mě páni programátoři, že jste si tohoto háku v návrhu algoritmu ještě nevšimli...
29.3.2009 23:16 CEST
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Hehe, prošel jsem dizkuzi až sem, abych taky zjistil, že až tebe trklo a nikoho před tebou, že ta rovnice je rovnice funkce a ne rovnice přímky (úsečky) v rovině. Jinak řešení je opravdu použít porovnání rozdílu abs A a B vůči nějaké konstantě určující přesnost.
Jardík avatar 30.3.2009 00:32 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
A no jo ... stane se, už je pozdě něco měnit, termín byl 23:59 :-(
Věřím v jednoho Boha.
30.3.2009 11:00 CEST
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Tak to myslim nebudes mit dobre, staci, aby ucitel zadal jednu usecku jako A[5,1], B[5,3] a jsi v riti, protoze dojde k deleni nulou (k je nekonecno).
30.3.2009 07:02 M. Lox | skóre: 12
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
A IMHO se přítomnost bodu na úsečce dá zjistit jednoduše:
Úsečka je A[a,b], B[c,d], bod C[e,f]. Bod, který leží na „její“ přímce leží i na úsečce, pokud platí: když je a<c, tak musí být a<e<c; když je a>c, tak a>e>c; když a=c, tak se testuje to samé s b, f a d (protože je rovnoběžná s y).
Nebo ne?
make menuconfig, not war!
30.3.2009 07:39 David Jaša | skóre: 44 | blog: Dejvův blog
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
jo

ale aby to mělo smysl, je potřeba napřed určit rovnoběžnost a shodnost - to ručně ještě před výpočtem průsečíku, pokud dotyčný programovací neumí korektně vyjádřit matematické konstrukce 0x = 0 (úsečky leží na jedné přímce, je potřeba spočítat překryv) a 0x != 0 (úsečky leží na dvou různých rovnoběžných přímkách).
Jardík avatar 30.3.2009 23:39 Jardík | skóre: 40 | blog: jarda_bloguje
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Tak jsem to spatlal s ax + by + c = 0, na progtest to už ale odeslat nemůžu. Ještě zítra na přednášce zkusím ukecat lektora, jestli by to ještě nevzal (cviko máme až ve čt), ale nejspíš ne.

Takto jsem řešil:
vektorový součin = 0 -> rovnoběžné/na společné přímce
  c1 == c2 -> na společné přímce
    A, B na CD nebo C na AB -> překrývají se
    jinak ne
  jinak rovnoběžné
skalární součin směrových vektorů = 0 -> kolmé
jinak různoběžné
ze soustavy průsečík (jako "zlomek", abych mohl přesně zjišťovat, jestli leží na úsečce)
průsečík na AB a CD -> průsečík úseček
Hlavní je, že to funguje, jenom by to asi příště chtělo pořádnou analýzu, což nemám rád :-)
Věřím v jednoho Boha.
31.3.2009 10:49 David Jaša | skóre: 44 | blog: Dejvův blog
Rozbalit Rozbalit vše Re: Průsečík dvou úseček
Hlavní je, že to funguje, jenom by to asi příště chtělo pořádnou analýzu, což nemám rád :-)
Hm, tak v tomhle se informatika od stavařiny moc neliší. Když se člověk vybodne na pořádnou analýzu, tak potom vycházejí v lepším případě nesmysly a v horším správně se tvářící úplně špatné výsledky...

Založit nové vláknoNahoru

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.