[python] Vykreslování grafů
Karel Šrot
karel.do.pekla.zajel na seznam.cz
Pátek Květen 25 09:30:38 CEST 2007
Jeste jsem si uvedomil, ze by vlastne bylo uplne nejlepsi kreslit ty
grafy jako grafy parametricky zadanych funkci, coz by umoznilo kreslit i
ruzne krivky. Ten vztah (f(a)-f(b))/(b-a) by mohl byt
|[x(a),y(a)]-[x(b),y(b])|(b-a)...tedy v citateli je vzdalenost bodu, na
ktere se zobrazi krajni body intervalu (pro parametr).
vzdalenost bodu [a1, b1], [a2, b2] je jak jiste vis
sqrt((a2-a1)^2+(b2-b1)^2)
Karel
Karel Šrot napsal(a):
> Zdravim,
>
> pocitat funkcni hodnoty a pak je spojit (lomenou) carou je naprosto
> bezny zpusob. Treba Maple (progrma pro symbolicke vypocty) pocita
> defaultne jen sto referencnich bodu. Pokud je v nejakem bode hodnota
> nedefinovana (deleni nulou), Maple ji ignoruje (tedy bodu je pak min a
> cara lomenejsi). Pomoci parametru lze specifikovat, zda se maji hledat
> body nespojitosti. V tom pripade se pomoci "sofistikovanych" algoritmu
> tyto body hledaji. Vcelku jednoduchou metodu Jan Jakubuv, ikdyz trochu
> nepresne. To, ze je funkce nespojita jeste neznamena, ze ma limitu v
> tomto bode rovnu nekonecnu.
>
> Ja osobne bych tu moznost hledani bodu nespojitosti pouzil, tedy pokud
> by uzivatel nic nezaskrtl, tak by se nehledaly a kresleni by bylo
> rychlejsi.
> V opacnem pripade bych se smiril s pomalosti a pouzil bych pro hledani
> bodu nespojitosti toto:
> Nejdrive si rozdelim cely interval na nekolik mensich, treba pomoci 200
> (ci vice) referencnich bodu. Budu mit treba seznam [[0,1], [1,2],
> [2,3],...]
>
> Neni-li funkce v nejakem bode X definovana, je to bod nespojitosti. Do
> seznamu ulozim hodnoty dva intervaly, pricemz pravy krajni bod prvniho
> je X-E, a levy krajni bod druheho X+E, kde E je dostatecne mala hodnota,
> ktera na grafu odpovida treba mene nez jednomu pixelu v grafu (to aby to
> nebylo poznat).
>
> Prochazim jednotlive intervaly a urcim tangens lomene cary, tedy
> (f(a)-f(b))/(b-a). Pokud by byl tangens v absolutni hodnote vetsi nez
> nejaka krajova zvolena hodnota (pro zacatek treba 5), bude interval
> podezrely. Ulozim interval do seznamu podezrelych intervalu. Az mam
> hotovo, prochazim kazdy podezrely interval.
> Rozdelim jej tedy napul a misto nej puvodniho mam ted dva intervaly.
> Pocitam totez pro oba a ten, ktery je stale podezrely (hodnota tangens
> bude v abs. hodnote jeste vetsi, nez byla predtim), budu zkoumat dal.
> Ten, co uz podezrely neni, tak dam ze seznamu podezrelych pryc. Kdyz by
> nahodou v polovine intervalu nebyla funkce spojita, pouziji to rozdeleni
> na dva intervaly s tim S-E, S+E a ani jeden z intervalu neberu za
> podezrely, protoze bod nespojitosti je mezi (tedy dam tyto intervaly
> mezi nepodezrele a koncim). Podezrele intervaly muzu okrajovat znova a
> znova, dokud hodnota tangens neprekroci nejakou danou mez. Pak
> prohlasim, ze na intervalu je funkce nespojita a tento interval kreslit
> nebudu. Protoze je strasne malej, tak to ani nebude vadit.
>
> Az mi to bude stacit, tak pospojuji vsechny nepodezrele intervaly. Takze
> seznam intervalu setridim, aby lezely za sebou. Pak je projdu odleva a
> kdyz dva sousedni maji spolecny krajni bod, tak je nahradim jednim
> velkym. Takze uplne nakonec budu mit seznam intervalu, kde je funkce
> spojita. V mezerach mezi temito intervaly jsou body nespojitosti, ale
> tyto mezery jsou male. Takze nakonec vykreslim gram funkce na kazdem z
> techto intervalu.
>
> Avsak kresneni nespojitych funkci je vzdy problem. Kdyz je funkce hodne
> divoka (jde rychle do nekonecna), tak se muze stat, ze vam pretece
> rozsah datoveho typu. Ale co se da delat.
>
> Snad to bylo trochu jasne, zkus si to kdyztak projit s tuzkou, papirem a
> grafem. Mnou uvedeny algoritmus bude potrebovat optimalizovat, protoze
> se tam zbytecne moc manipuluje se seznamy a tak. Lze ho navrhnout lip,
> ale ja zvolil tuto formu kvuli srozumitelnosti. Az ho pochopis, tak
> jiste prijdes na to, ze se obejdes bez nadbytecneho vytvareni seznamu
> itervalu.
>
> No snad ti to pomuze, preci jen me to stalo trictvrte hodiny zivota. :-)
>
> Karel
>
>
>> 2) Nevím jak vy byste vypočítávali body pro vykreslení grafu, ale já
>> na to mám takovoutu metodu:
>>
>> cislo=spodni_hranice
>> while cislo < horni_hranice:
>> x=cislo
>> y=eval(funkce.replace('x',cislo))
>> body.append([x,y])
>> cislo=cislo+preciznost
>>
>> Ale výpočet se mi zdá poměrně dlouhý a tak se ptám jesetli vás
>> nenapadá něco efektivnějšího. Dále jakou hodnotu by měla mít proměnná
>> preciznost (nebo jestli by měl mít uživatel možnost ji nastavit).
>> 3) Nyní program dostává body jako souřadnice x,y a vykresluje
>> jednotlivé pixely. Pochopitelně je to způsob relativně nepřehledný,
>> protože pak může být na plátně jenom několik nic neříkajicích teček a
>> proto by je chtělo nějak spojit. Napadlo mě spojit každé dva vedlejší
>> body čárou ale pak mi došlo že to je nemožné, například kvůli grafu
>> 1/cos(x). Nevíte jaký způsob používají jiné programy?
>>
>>
>> Děkuji za případné odpovědi.
>>
>> Jakub Vojáček.
Další informace o konferenci Python