MainPage.xaml.cs
// theory to Mandelbrot set: http://www.ddewey.net/mandelbrot/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging; // for WriteableBitmap
using System.Windows.Threading; // for DispatcherTimer
namespace MandelbrotSet
{
public partial class MainPage : UserControl
{
WriteableBitmap m_RenderTarget;
DateTime m_LastUpdate;
int width = 600;
int height = 400;
RECT rectClient;
float xmin = -3;
float xmax = 3;
float ymin = -2;
float ymax = 2;
float zoom = 1;
int flagMove;
public MainPage()
{
InitializeComponent();
this.KeyDown += new KeyEventHandler(MainPage_KeyDown);
this.KeyUp += new KeyEventHandler(MainPage_KeyUp);
m_RenderTarget = new WriteableBitmap(width, height);
image1.Source = m_RenderTarget;
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new System.TimeSpan(0, 0, 0, 0, 1);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
m_LastUpdate = DateTime.Now;
rectClient.left = 0;
rectClient.right = 600;
rectClient.top = 0;
rectClient.bottom = 400;
}
void timer_Tick(object sender, EventArgs e)
{
UpdateScene();
}
private void UpdateScene()
{
DateTime now = DateTime.Now;
float deltaTime = (float)now.Subtract(m_LastUpdate).TotalSeconds;
m_LastUpdate = now;
Utilities.FillRect(rectClient, Utilities.RGBA(150, 150, 0, 255), m_RenderTarget.Pixels);
text3.Text = string.Format("frame rate: {0}", 1.0f / deltaTime);
MoveScreenView();
MandelbrotSet();
m_RenderTarget.Invalidate();
}
void MandelbrotSet()
{
int iter;
ComplexNumber c;
ComplexNumber z;
float temp;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
c.x = (float)(xmax - xmin) / width * ((float)i) + xmin;
c.y = (float) (ymax - ymin) / height * ((float)j) + ymin;
z.x = 0; z.y = 0;
iter = 0;
while (Math.Sqrt(z.x * z.x + z.y * z.y) <= 2 && iter < 30)
{
temp = z.x;
z.x = z.x * z.x - z.y * z.y + c.x;
z.y = 2.0f * temp * z.y + c.y;
iter++;
}
m_RenderTarget.Pixels[j * width + i] = Utilities.RGBA((byte)(100 + 3 * iter), (byte)(100 + 3 * iter), (byte)(100 + 3 * iter), 255);
}
}
}
void MainPage_KeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Up:
flagMove |= (1 << 0);
break;
case Key.Down:
flagMove |= (1 << 1);
break;
case Key.Left:
flagMove |= (1 << 2);
break;
case Key.Right:
flagMove |= (1 << 3);
break;
case Key.I:
flagMove |= (1 << 4);
break;
case Key.O:
flagMove |= (1 << 5);
break;
}
}
void MainPage_KeyUp(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Up:
flagMove ^= (1 << 0);
break;
case Key.Down:
flagMove ^= (1 << 1);
break;
case Key.Left:
flagMove ^= (1 << 2);
break;
case Key.Right:
flagMove ^= (1 << 3);
break;
case Key.I:
flagMove ^= (1 << 4);
break;
case Key.O:
flagMove ^= (1 << 5);
break;
}
}
void MoveScreenView()
{
float step = 0.05f * (xmax - xmin);
if (0 != (flagMove & (1 << 0))) { ymin += step; ymax += step; } // UP
if (0 != (flagMove & (1 << 1))) { ymin -= step; ymax -= step; } // DOWN
if (0 != (flagMove & (1 << 2))) { xmin += step; xmax += step; } // LEFT
if (0 != (flagMove & (1 << 3))) { xmin -= step; xmax -= step; } // RIGHT
if (0 != (flagMove & (1 << 4))) // I
{
xmin = (xmin + xmax) / 2.0f - (xmax - xmin) / 2.1f;
xmax = (xmin + xmax) / 2.0f + (xmax - xmin) / 2.1f;
ymin = (ymin + ymax) / 2.0f - (ymax - ymin) / 2.1f;
ymax = (ymin + ymax) / 2.0f + (ymax - ymin) / 2.1f;
}
if (0 != (flagMove & (1 << 5))) // O
{
xmin = (xmin + xmax) / 2.0f - (xmax - xmin) / 1.9f;
xmax = (xmin + xmax) / 2.0f + (xmax - xmin) / 1.9f;
ymin = (ymin + ymax) / 2.0f - (ymax - ymin) / 1.9f;
ymax = (ymin + ymax) / 2.0f + (ymax - ymin) / 1.9f;
}
}
}
}