Fractalen
-
Hoi Berend,
Ik heb een mandelbrot fractal geprogrammeerd in de C# met Visual Studio. Om een kleur de maken in een pictureBox kun je gebruik maken van Color.FromArgb(0, 0, 0) (<- bijvoorbeeld). In plaats van deze notitie wijze, werd mij verteld over de notatie
'pic.SetPixel(x, y, Color.FromArgb(loopgo % 128 * 2, loopgo % 32 * 7, loopgo % 16 * 14));'
pic is de afbeelding en loopgo = 0.
Hoe kan het dat er zoveel verschillende kleuren hierdoor ontstaan?
Groet, Ganesh
p.s. wil je misschien de hele broncode hebben?
-
Hoi Ganesh,
Volgens mij begrijp ik je vraag nog niet helemaal goed. Hoe heb je je fractaal geprogrammeerd en waarom vind je het gek dat bepaalde kleuren op een plaats zitten?
-
Half..ik snap nog niet precies hoe die pixels verschillende kleuren krijgen..
-
Beste Ganesh,
'loopgo' is feitelijk een counter. Het is een teller die een heleboel keer opgehoogd wordt (door 'loopgo++', dit betekent eigenlijk 'loopgo = loopgo + 1'). Vervolgens wordt er gecheckt of 'loopgo' na de ophoging niet groter is dan 'loopmax' (loopgo != loopmax). De pixel krijgt een kleur die afhankelijk is van 'loopgo' en aangezien die waarde elke iteratie veranderd, krijg je ook een heleboel kleuren in je fractaal.
Is dat een beetje duidelijk voor je?
-
Dit is de code, als je het bestand helemaal wilt hebben, dan heb ik je e-mail nodig.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace PWS_Fractal { public partial class Form1 : Form { static double pXmax = 0; static double pXmin = 0; static double pYmax = 0; static double pYmin = 0; public Form1() { InitializeComponent(); KeyDown += new KeyEventHandler(Form1_KeyDown); } private void Form1_KeyDown(object sender, KeyEventArgs e) { int x = pictureBox1.Location.X; int y = pictureBox1.Location.Y; if (e.KeyCode == Keys.Right) x += 5; else if (e.KeyCode == Keys.Left) x -= 5; else if (e.KeyCode == Keys.Up) y -= 5; else if (e.KeyCode == Keys.Down) y += 5; } private void Form1_Load(object sender, EventArgs e) { Bitmap pic = MandelbrotSet(pictureBox1, 2, -2, 2, -2); pictureBox1.Image = pic; } static Bitmap MandelbrotSet(PictureBox pictureBox1, double Xmax, double Xmin, double Ymax, double Ymin) { pXmax = Xmax; pYmax = Ymax; pXmin = Xmin; pYmin = Ymin; Bitmap pic = new Bitmap(pictureBox1.Width, pictureBox1.Height); double zx = 0; double zy = 0; double cx = 0; double cy = 0; double xzoom = ((Xmax - Xmin) / Convert.ToDouble(pic.Width)); double yzoom = ((Ymax - Ymin) / Convert.ToDouble(pic.Height)); double tempzx = 0; int loopmax = 1000; int loopgo = 0; for (int x = 0; x < pic.Width; x++) { cx = (xzoom * x) - Math.Abs(Xmin); for (int y = 0; y < pic.Height; y++) { zx = 0; zy = 0; cy = (yzoom * y) - Math.Abs(Ymin); loopgo = 0; while (zx * zx + zy * zy <= 4 && loopgo < loopmax) { loopgo++; tempzx = zx; zx = (zx * zx) - (zy * zy) + cx; zy = (2 * tempzx * zy) + cy; } if (loopgo != loopmax) pic.SetPixel(x, y, Color.FromArgb(loopgo % 128 * 2, loopgo % 32 * 7, loopgo % 16 * 14)); else pic.SetPixel(x, y, Color.Black); } } return pic; } private void button1_Click(object sender, EventArgs e) { Bitmap pic = MandelbrotSet(pictureBox1, 2, -2, 2, -2); pictureBox1.Image.Dispose(); pictureBox1.Image = pic; } private void button2_Click(object sender, EventArgs e) { saveFileDialog1.FileName = "Fractal"; ImageFormat format = ImageFormat.Jpeg; if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) { pictureBox1.Image.Save(saveFileDialog1.FileName, format); } } private void pictureBox1_MouseClick(object sender, MouseEventArgs e) { int Cx = e.X; int Cy = e.Y; double Xzoom = ((pXmax - pXmin) / Convert.ToDouble(pictureBox1.Width)); double Yzoom = ((pYmax - pYmin) / Convert.ToDouble(pictureBox1.Height)); int zoomx = pictureBox1.Width / 5; int zoomy = pictureBox1.Height / 5; Bitmap pic = MandelbrotSet(pictureBox1, ((Cx + zoomx) * Xzoom) - Math.Abs(pXmin), ((Cx - zoomx) * Xzoom) - Math.Abs(pXmin), ((Cy + zoomy) * Yzoom) - Math.Abs(pYmin), ((Cy - zoomy) * Yzoom) - Math.Abs(pYmin)); pictureBox1.Image.Dispose(); pictureBox1.Image = pic; } private void button3_Click(object sender, EventArgs e) { MessageBox.Show(" Muis - Klik één keer met de muis op een locatie in de afbeelding \n en deze zal inzoomen op deze locatie.\n Reset - Brengt de afbeeling terug naar originele staat. \n Opslaan - Slaat de afbeeling op. (JPEG, PNG of Bitmap)", "Help", MessageBoxButtons.OK, MessageBoxIcon.Question); } private void button4_Click(object sender, EventArgs e) { this.Close(); } public string Filter { get; set; } public static double Ymin { get; set; } public static double Xmin { get; set; } public static double Ymax { get; set; } public static double Xmax { get; set; } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { label1.Text = e.X - (pictureBox1.Width / 2) + ""; label2.Text = e.Y - (pictureBox1.Height / 2) + ""; } } }
-
Hi Ganesh,
Het is misschien goed om de hele broncode te laten zien, want volgens mij is je loopgo een iteratief onderdeel die dus de kleuren geeft aan pixels afhankelijk van waar je bent in het iteratieve proces. Dat wil zeggen, je kleuren zijn afhankelijk van het aantal iteraties dat je code maakt om de Mandelbrot fractal te berekenen/te plotten.
-
Hi Ganesh,
Laten we er dan wat dieper induiken! Bij deze een gesimplificeerde versie van de code met tekst en uitleg als plaatje. Maar eerst even wat basisprincipes.
For loop
For (x=0; x < xMax; x++) { SOME CODE; }
Dit betekent dat hij het stuk tussen de haakjes net zo lang herhaalt (‘loop’) totdat x niet meer kleiner is dan xMax. X++ geeft aan dat na elke looping x met ééntje moet worden verhoogd. Stel dat we SOME CODE vervangen door ‘return x;’ dan wordt de output dus 0,1,2,3,…..,xMax-1.
While loop
X=0; While (x<xMax) { SOME CODE; X++; }
Deze loop doet eigenlijk hetzelfde als de for loop, maar je moet op andere plekken aangeven dat x groter moet worden (anders blijven de loop zich eindeloos herhalen) en de beginwaarde aangeven.
Tekst en uitleg bij jouw code
-
Er staat niet alleen 128 * 2, maar er staat loopgo % 128 * 2. Dat eerste herken je misschien niet, maar dat is een restwaarde-operator. Het getal is de restwaarde van loopgo/128. Voorbeeld: stel je voor loopgo is 130, dan is de restwaarde 2. Omdat de operators van vermenigvuldiging, deling en restwaarde dezelfde prioriteit hebben, worden ze in volgorde uitgevoerd. Er staat dus eigenlijk (loopgo%128)*2. Indien loopgo dus 130 zou zijn, wordt dit door de vermenigvuldiging 4. Als het loopgo%256 zou zijn, werd het 130.
Kijk voor meer info over operators ook hier: http://msdn.microsoft.com/en-us/library/6a71f45d.aspx
-
en waarom 128 * 2 en niet gewoon 256?
-
Geweldig! Hartstikke bedankt!
-
Ik ga toch weer doorvragen. Hoe wordt de zwarte vorm in het midden gevormd?
-
Geen probleem, Ganesh, daar is het forum voor! Kan je een plaatje bij je bericht plakken, dan begrijp ik beter waar je het over hebt!
-
Bedankt voor de melding, ik hoop dat je iemand vindt.
-
Ha Ganesh,
Berend is op dit moment in het buitenland en kan tijdelijk geen reactie geven op jouw bericht. Ik zal een andere student aanspreken jou te helpen. Excuses voor het ongemak.
Groet,
Noor -
Ik heb even een URL, mijn eigen fractal kan ik niet uploaden. De vorm is precies hetzelfde.