Vzdálenost souřadnice Ay bodu A[Ax;Ay] od osy x ježícího na parabole je dána rovnicí y=a*x^2+b*x+c. Způsob, jakým vynést graf paraboly by tedy mohl vypadat nějak takto:
Dim b = New Bitmap(400,400)
Dim g = Graphics.FromImage(b)
g.TranslateTransform(200,200) ' umístíme nulu souřadnicové systému doprostřed obrázku
Dim y As Integer
Dim a,b,c As Double ' dosadíte si řídící proměnné paraboly
For x=-200 To 200
y=a*x^2+b*x+c
g.DrawRectangle(Brushes.Black,x,y,1,1)
Next
Samozřejmě možností je více. 1.) Lepší, než kreslení pixelů by bylo kreslit rovnou křivku z daných bodů, vypadalo by to lépe díky antialiasingu. Algoritmus pro tento postup by byl: V každém kroku cyklu, pokud a) uložení bod neexistuje, nakreslit pixel b) uložený bod existuje, nakreslit čáru od uloženého bodu do současných koordinátů a uložený bod nahradit aktuálním bodem 2.) Ještě lepší by pak bylo mít sadu bodů a tu předat do DrawCurve. 3.) Nejlepší jak z hlediska objemu kódu, tak z hlediska výpočetní náročnosti by bylo aproximovat parabolu pomocí kruhové (resp. elipsové) výseče, pokud je graf pouze informační a jde opravdu pouze o graf - nebudete používat parabolu pro další výpočty. Zkrátka pokud si můžete dovolit nepřesnosti. Jak zjistit rozměry paraboly byste měl být schopen vydedukovat, pokud si o parabole něco přečtete. Na wikipedii je hezky zpracovaný jak český, tak anglický článek. Kód ve ve Visual Basic .NET, bude třeba si jej převést do C#. Zdroje: http://cs.wikipedia.org/wiki/Parabola_%2... http://en.wikipedia.org/wiki/Parabola http://www.codeproject.com/Articles/3278... EDIT: Trochu jsem si s tím hrál a tady je výsledek. Vytvořil jsem Extension metodu, která přebere jako parametr bitmapu, pero a parametry paraboly a vykreslí ji pomocí DrawCurve:
<System.Runtime.CompilerServices.Extension()> _
Public Sub PlotParabola(bitmap As Bitmap, pen As Pen, a As Double, b As Double, c As Double)
Using canvas = Graphics.FromImage(bitmap)
canvas.TranslateTransform(bitmap.Width / 2, bitmap.Height / 2)
canvas.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
With canvas.VisibleClipBounds
canvas.DrawCurve(pen, Enumerable.Range(.Left, .Width).Select(Function(x) New PointF(x, a * (x ^ 2) + b * x + c)).ToArray())
End With
End Using
End Sub
Použití je zřejmé:
Dim b As New Bitmap(400, 400)
b.PlotParabola(Pens.Blue, 0.1, 2, 0)
b.PlotParabola(Pens.Maroon, 0.2, 2, 10)
b.PlotParabola(Pens.Green, 0.3, 2, 20)
b.PlotParabola(Pens.Yellow, 0.4, 2, 30)
PictureBox1.Image = b
Opět platí, že veškerý kód je ve VB .NET. Ovšem je důležité podotknout, že by bylo lepší udělat to jako Extension metodu k objektu Graphics. Musíte mít na paměti, že v takovém případě by transformace buď odpadla úplně (resp. transformovat byste to musel mimo tělo metody) a nebo byste to transformoval jako to dělám já, ale u konce metody byste transformoval zase zpět! Jinak by se stalo to, že po každém zavolání metody by Vám střed odjížděl. Jak vidíte, metoda je rychlá, protože iteruje pouze potřebnou oblast osy x (viditelné souřadnice zleva až do prava, ne celý objekt Graphics), pokud budete chtít, můžete také přidat podmínku, která zajistí, že se použijí pouze hodnoty x, které budou vracet viditelné výsledky na ose y. Opět je nasnadě studium rovnice paraboly a základní porozumění kuželosečkám. A ještě jedna poznámka nakonec: transformace, kterou provádím já pouze posune střed vykreslování do viditelného regionu grafiky. Správná transformace by ale měla být taková, která převrátí y osu (protože na monitoru y stoupá směrem dolů, v grafech ale stoupá směrem vzhůru) a posune do středu pouze po x, y by se mělo posunout odspodu na nějakou rozumnější hodnotu, například vzdálenost paty paraboly od řídící přímky, což je polovina vzdálenosti ohniska (velikost parametru).
|